line
stmt
bran
cond
sub
pod
time
code
1
package Geo::FIT;
2
18
18
997439
use strict;
18
36
18
1725
3
18
18
121
use warnings;
18
37
18
1896
4
5
our $VERSION = '1.13';
6
7
=encoding utf-8
8
9
=head1 NAME
10
11
Geo::FIT - Decode Garmin FIT files
12
13
=head1 SYNOPSIS
14
15
use Geo::FIT;
16
17
Create an instance, assign a FIT file to it, open it:
18
19
my $fit = Geo::FIT->new();
20
$fit->file( $fname );
21
$fit->open or die $fit->error;
22
23
Register a callback to get some info on where we've been and when:
24
25
my $record_callback = sub {
26
my ($self, $descriptor, $values) = @_;
27
28
my $time= $self->field_value( 'timestamp', $descriptor, $values );
29
my $lat = $self->field_value( 'position_lat', $descriptor, $values );
30
my $lon = $self->field_value( 'position_long', $descriptor, $values );
31
32
print "Time was: ", join("\t", $time, $lat, $lon), "\n"
33
};
34
35
$fit->data_message_callback_by_name('record', $record_callback ) or die $fit->error;
36
37
my @header_things = $fit->fetch_header;
38
39
1 while ( $fit->fetch );
40
41
$fit->close;
42
43
=head1 DESCRIPTION
44
45
C is a Perl class to provide interfaces to decode Garmin FIT files (*.fit).
46
47
The module also provides a script to read and print the contents of FIT files (L), a script to convert FIT files to TCX files (L), and a script to convert a locations file to GPX format (L).
48
49
=cut
50
51
18
18
128
use Carp qw/ croak /;
18
43
18
1416
52
18
18
10143
use FileHandle;
18
219997
18
120
53
18
18
19436
use POSIX qw(BUFSIZ);
18
165689
18
140
54
18
18
45850
use Time::Local;
18
57268
18
1547
55
18
18
164
use Scalar::Util qw(blessed looks_like_number);
18
34
18
2697
56
57
my $uint64_invalid;
58
BEGIN {
59
18
18
71
eval { $uint64_invalid = unpack('Q', pack('a', -1)) };
18
73
60
18
50
76
unless (defined $uint64_invalid) {
61
18
29791
require Math::BigInt;
62
18
1006764
import Math::BigInt
63
}
64
}
65
66
require Exporter;
67
our @ISA = qw(Exporter);
68
our @EXPORT = qw(
69
FIT_ENUM
70
FIT_SINT8
71
FIT_UINT8
72
FIT_SINT16
73
FIT_UINT16
74
FIT_SINT32
75
FIT_UINT32
76
FIT_SINT64
77
FIT_UINT64
78
FIT_STRING
79
FIT_FLOAT32
80
FIT_FLOAT64
81
FIT_UINT8Z
82
FIT_UINT16Z
83
FIT_UINT32Z
84
FIT_UINT64Z
85
FIT_BYTE
86
FIT_BASE_TYPE_MAX
87
FIT_HEADER_LENGTH
88
);
89
90
sub FIT_ENUM() {0;}
91
sub FIT_SINT8() {1;}
92
sub FIT_UINT8() {2;}
93
sub FIT_SINT16() {3;}
94
sub FIT_UINT16() {4;}
95
sub FIT_SINT32() {5;}
96
sub FIT_UINT32() {6;}
97
sub FIT_STRING() {7;}
98
sub FIT_FLOAT32() {8;}
99
sub FIT_FLOAT64() {9;}
100
sub FIT_UINT8Z() {10;}
101
sub FIT_UINT16Z() {11;}
102
sub FIT_UINT32Z() {12;}
103
sub FIT_BYTE() {13;}
104
sub FIT_SINT64() {14;}
105
sub FIT_UINT64() {15;}
106
sub FIT_UINT64Z() {16;}
107
sub FIT_BASE_TYPE_MAX() {FIT_UINT64Z;}
108
109
my ($rechd_offset_compressed_timestamp_header, $rechd_mask_compressed_timestamp_header,
110
$rechd_offset_cth_local_message_type, $rechd_length_cth_local_message_type,
111
$rechd_mask_cth_local_message_type, $rechd_length_cth_timestamp, $rechd_mask_cth_timestamp,
112
$rechd_offset_definition_message, $rechd_mask_definition_message, $rechd_offset_devdata_message,
113
$rechd_mask_devdata_message, $rechd_length_local_message_type, $rechd_mask_local_message_type,
114
$cthd_offset_local_message_type, $cthd_length_local_message_type, $cthd_mask_local_message_type,
115
$cthd_length_time_offset, $cthd_mask_time_offset
116
);
117
118
$rechd_offset_compressed_timestamp_header = 7;
119
$rechd_mask_compressed_timestamp_header = 1 << $rechd_offset_compressed_timestamp_header;
120
$rechd_offset_cth_local_message_type = 5;
121
$rechd_length_cth_local_message_type = 2;
122
$rechd_mask_cth_local_message_type = ((1 << $rechd_length_cth_local_message_type) - 1) << $rechd_offset_cth_local_message_type;
123
$rechd_length_cth_timestamp = $rechd_offset_cth_local_message_type;
124
$rechd_mask_cth_timestamp = (1 << $rechd_length_cth_timestamp) - 1;
125
$rechd_offset_definition_message = 6;
126
$rechd_mask_definition_message = 1 << $rechd_offset_definition_message;
127
$rechd_offset_devdata_message = 5;
128
$rechd_mask_devdata_message = 1 << $rechd_offset_devdata_message;
129
$rechd_length_local_message_type = 4;
130
$rechd_mask_local_message_type = (1 << $rechd_length_local_message_type) - 1;
131
$cthd_offset_local_message_type = 5;
132
$cthd_length_local_message_type = 2;
133
$cthd_mask_local_message_type = (1 << $cthd_length_local_message_type) - 1;
134
$cthd_length_time_offset = 5;
135
$cthd_mask_time_offset = (1 << $cthd_length_time_offset) - 1;
136
137
my ($defmsg_min_template, $defmsg_min_length);
138
$defmsg_min_template = 'C C C S C';
139
$defmsg_min_length = length(pack($defmsg_min_template));
140
141
my ($deffld_template, $deffld_length, $deffld_mask_endian_p, $deffld_mask_type);
142
$deffld_template = 'C C C';
143
$deffld_length = length(pack($deffld_template));
144
$deffld_mask_endian_p = 1 << 7;
145
$deffld_mask_type = (1 << 5) - 1;
146
147
my ($devdata_min_template, $devdata_min_length, $devdata_deffld_template, $devdata_deffld_length);
148
$devdata_min_template = 'C';
149
$devdata_min_length = length(pack($devdata_min_template));
150
$devdata_deffld_template = 'C C C';
151
$devdata_deffld_length = length(pack($deffld_template));
152
153
my @invalid = (0xFF) x ($deffld_mask_type + 1);
154
$invalid[FIT_SINT8] = 0x7F;
155
$invalid[FIT_SINT16] = 0x7FFF;
156
$invalid[FIT_UINT16] = 0xFFFF;
157
$invalid[FIT_SINT32] = 0x7FFFFFFF;
158
$invalid[FIT_UINT32] = 0xFFFFFFFF;
159
$invalid[FIT_STRING] = $invalid[FIT_UINT8Z] = $invalid[FIT_UINT16Z] = $invalid[FIT_UINT32Z] = $invalid[FIT_UINT64Z] = 0;
160
#$invalid[FIT_FLOAT32] = NaN;
161
#$invalid[FIT_FLOAT64] = NaN;
162
$invalid[FIT_FLOAT32] = unpack('f', pack('V', 0xFFFFFFFF));
163
$invalid[FIT_FLOAT64] = unpack('d', pack('V V', 0xFFFFFFFF, 0xFFFFFFFF));
164
165
my ($big_int_base32, $sint64_2c_mask, $sint64_2c_base, $sint64_2c_sign);
166
167
if (defined $uint64_invalid) {
168
$invalid[FIT_UINT64] = $uint64_invalid;
169
$invalid[FIT_SINT64] = eval '0x7FFFFFFFFFFFFFFF';
170
} else {
171
$invalid[FIT_UINT64] = Math::BigInt->new('0xFFFFFFFFFFFFFFFF');
172
$invalid[FIT_SINT64] = Math::BigInt->new('0x7FFFFFFFFFFFFFFF');
173
$big_int_base32 = Math::BigInt->new('0x100000000');
174
$sint64_2c_mask = Math::BigInt->new('0xFFFFFFFFFFFFFFFF');
175
$sint64_2c_base = Math::BigInt->new('0x10000000000000000');
176
$sint64_2c_sign = Math::BigInt->new('0x1000000000000000');
177
}
178
179
sub packfilter_uint64_big_endian {
180
0
0
0
0
my @res = $_[0]->bdiv($big_int_base32);
181
0
0
@res;
182
}
183
184
sub packfilter_uint64_little_endian {
185
0
0
0
0
my @res = $_[0]->bdiv($big_int_base32);
186
0
0
@res[1, 0];
187
}
188
189
my $my_endian = unpack('L', pack('N', 1)) == 1 ? 1 : 0;
190
191
*packfilter_uint64 = $my_endian ? \&packfilter_uint64_big_endian : \&packfilter_uint64_little_endian;
192
193
sub unpackfilter_uint64_big_endian {
194
0
0
0
0
my ($hi, $lo) = @_;
195
0
0
Math::BigInt->new($hi)->blsft(32)->badd($lo);
196
}
197
198
sub unpackfilter_uint64_little_endian {
199
0
0
0
0
&unpackfilter_uint64_big_endian(@_[1, 0]);
200
}
201
202
*unpackfilter_uint64 = $my_endian ? \&unpackfilter_uint64_big_endian : \&unpackfilter_uint64_little_endian;
203
204
sub packfilter_sint64_big_endian {
205
0
0
0
0
0
if ($_[0]->bcmp(0) < 0) {
206
0
0
&packfilter_uint64_big_endian($sint64_2c_mask->band($sint64_2c_base->badd($_[0])));
207
} else {
208
0
0
&packfilter_uint64_big_endian($_[0]);
209
}
210
}
211
212
sub packfilter_sint64_little_endian {
213
0
0
0
0
0
if ($_[0]->bcmp(0) < 0) {
214
0
0
&packfilter_uint64_little_endian($sint64_2c_mask->band($sint64_2c_base->badd($_[0])));
215
} else {
216
0
0
&packfilter_uint64_little_endian($_[0]);
217
}
218
}
219
220
*packfilter_sint64 = $my_endian ? \&packfilter_sint64_big_endian : \&packfilter_sint64_little_endian;
221
222
sub unpackfilter_sint64_big_endian {
223
0
0
0
0
my ($hi, $lo) = @_;
224
0
0
my $n = Math::BigInt->new($hi)->blsft(32)->badd($lo)->band($sint64_2c_mask);
225
226
0
0
0
if ($n->band($sint64_2c_sign)->bcmp(0) == 0) {
227
0
0
$n;
228
} else {
229
0
0
$n->bsub($sint64_2c_base);
230
}
231
}
232
233
sub unpackfilter_sint64_little_endian {
234
0
0
0
0
&unpackfilter_sint64_big_endian(@_[1, 0]);
235
}
236
237
*unpackfilter_sint64 = $my_endian ? \&unpackfilter_sint64_big_endian : \&unpackfilter_sint64_little_endian;
238
239
sub invalid {
240
0
0
1
0
my ($self, $type) = @_;
241
0
0
$invalid[$type & $deffld_mask_type];
242
}
243
244
my @size = (1) x ($deffld_mask_type + 1);
245
$size[FIT_SINT16] = $size[FIT_UINT16] = $size[FIT_UINT16Z] = 2;
246
$size[FIT_SINT32] = $size[FIT_UINT32] = $size[FIT_UINT32Z] = $size[FIT_FLOAT32] = 4;
247
$size[FIT_FLOAT64] = $size[FIT_SINT64] = $size[FIT_UINT64] = $size[FIT_UINT64Z] = 8;
248
249
my (@template, @packfactor, @packfilter, @unpackfilter);
250
@template = ('C') x ($deffld_mask_type + 1);
251
@packfactor = (1) x ($deffld_mask_type + 1);
252
@packfilter = (undef) x ($deffld_mask_type + 1);
253
@unpackfilter = (undef) x ($deffld_mask_type + 1);
254
255
$template[FIT_SINT8] = 'c';
256
$template[FIT_SINT16] = 's';
257
$template[FIT_UINT16] = $template[FIT_UINT16Z] = 'S';
258
$template[FIT_SINT32] = 'l';
259
$template[FIT_UINT32] = $template[FIT_UINT32Z] = 'L';
260
$template[FIT_FLOAT32] = 'f';
261
$template[FIT_FLOAT64] = 'd';
262
263
if (defined $uint64_invalid) {
264
$template[FIT_SINT64] = 'q';
265
$template[FIT_UINT64] = $template[FIT_UINT64Z] = 'Q';
266
} else {
267
$template[FIT_SINT64] = $template[FIT_UINT64] = $template[FIT_UINT64Z] = 'L';
268
$packfactor[FIT_SINT64] = $packfactor[FIT_UINT64] = $packfactor[FIT_UINT64Z] = 2;
269
$packfilter[FIT_SINT64] = \&packfilter_sint64;
270
$unpackfilter[FIT_SINT64] = \&unpackfilter_sint64;
271
$packfilter[FIT_UINT64] = $packfilter[FIT_UINT64Z] = \&packfilter_uint64;
272
$unpackfilter[FIT_UINT64] = $unpackfilter[FIT_UINT64Z] = \&unpackfilter_uint64;
273
}
274
275
my %named_type = (
276
'file' => +{
277
'_base_type' => FIT_ENUM,
278
'device' => 1,
279
'settings' => 2,
280
'sport' => 3,
281
'activity' => 4,
282
'workout' => 5,
283
'course' => 6,
284
'schedules' => 7,
285
'weight' => 9,
286
'totals' => 10,
287
'goals' => 11,
288
'blood_pressure' => 14,
289
'monitoring_a' => 15,
290
'activity_summary' => 20,
291
'monitoring_daily' => 28,
292
'monitoring_b' => 32,
293
'segment' => 34,
294
'segment_list' => 35,
295
'exd_configuration' => 40,
296
'mfg_range_min' => 0xF7,
297
'mfg_range_max' => 0xFE,
298
},
299
300
'mesg_num' => +{
301
'_base_type' => FIT_UINT16,
302
'file_id' => 0,
303
'capabilities' => 1,
304
'device_settings' => 2,
305
'user_profile' => 3,
306
'hrm_profile' => 4,
307
'sdm_profile' => 5,
308
'bike_profile' => 6,
309
'zones_target' => 7,
310
'hr_zone' => 8,
311
'power_zone' => 9,
312
'met_zone' => 10,
313
'sport' => 12,
314
'goal' => 15,
315
'session' => 18,
316
'lap' => 19,
317
'record' => 20,
318
'event' => 21,
319
'source' => 22, # undocumented
320
'device_info' => 23,
321
'workout' => 26,
322
'workout_step' => 27,
323
'schedule' => 28,
324
'location' => 29, # undocumented
325
'weight_scale' => 30,
326
'course' => 31,
327
'course_point' => 32,
328
'totals' => 33,
329
'activity' => 34,
330
'software' => 35,
331
'file_capabilities' => 37,
332
'mesg_capabilities' => 38,
333
'field_capabilities' => 39,
334
'file_creator' => 49,
335
'blood_pressure' => 51,
336
'speed_zone' => 53,
337
'monitoring' => 55,
338
'training_file' => 72,
339
'hrv' => 78,
340
'ant_rx' => 80,
341
'ant_tx' => 81,
342
'ant_channel_id' => 82,
343
'length' => 101,
344
'monitoring_info' => 103,
345
'battery' => 104, # undocumented
346
'pad' => 105,
347
'slave_device' => 106,
348
'connectivity' => 127,
349
'weather_conditions' => 128,
350
'weather_alert' => 129,
351
'cadence_zone' => 131,
352
'hr' => 132,
353
'segment_lap' => 142,
354
'memo_glob' => 145,
355
'sensor' => 147, # undocumented
356
'segment_id' => 148,
357
'segment_leaderboard_entry' => 149,
358
'segment_point' => 150,
359
'segment_file' => 151,
360
'workout_session' => 158,
361
'watchface_settings' => 159,
362
'gps_metadata' => 160,
363
'camera_event' => 161,
364
'timestamp_correlation' => 162,
365
'gyroscope_data' => 164,
366
'accelerometer_data' => 165,
367
'three_d_sensor_calibration' => 167,
368
'video_frame' => 169,
369
'obdii_data' => 174,
370
'nmea_sentence' => 177,
371
'aviation_attitude' => 178,
372
'video' => 184,
373
'video_title' => 185,
374
'video_description' => 186,
375
'video_clip' => 187,
376
'ohr_settings' => 188,
377
'exd_screen_configuration' => 200,
378
'exd_data_field_configuration' => 201,
379
'exd_data_concept_configuration' => 202,
380
'field_description' => 206,
381
'developer_data_id' => 207,
382
'magnetometer_data' => 208,
383
'barometer_data' => 209,
384
'one_d_sensor_calibration' => 210,
385
'monitoring_hr_data' => 211,
386
'time_in_zone' => 216,
387
'set' => 225,
388
'stress_level' => 227,
389
'max_met_data' => 229,
390
'dive_settings' => 258,
391
'dive_gas' => 259,
392
'dive_alarm' => 262,
393
'exercise_title' => 264,
394
'dive_summary' => 268,
395
'spo2_data' => 269,
396
'sleep_level' => 275,
397
'jump' => 285,
398
'aad_accel_features' => 289,
399
'beat_intervals' => 290,
400
'respiration_rate' => 297,
401
'hsa_accelerometer_data' => 302,
402
'hsa_step_data' => 304,
403
'hsa_spo2_data' => 305,
404
'hsa_stress_data' => 306,
405
'hsa_respiration_data' => 307,
406
'hsa_heart_rate_data' => 308,
407
'split' => 312,
408
'split_summary' => 313,
409
'hsa_body_battery_data' => 314,
410
'hsa_event' => 315,
411
'climb_pro' => 317,
412
'tank_update' => 319,
413
'tank_summary' => 323,
414
'sleep_assessment' => 346,
415
'hrv_status_summary' => 370,
416
'hrv_value' => 371,
417
'raw_bbi' => 372,
418
'device_aux_battery_info' => 375,
419
'hsa_gyroscope_data' => 376,
420
'chrono_shot_session' => 387,
421
'chrono_shot_data' => 388,
422
'hsa_configuration_data' => 389,
423
'dive_apnea_alarm' => 393,
424
'skin_temp_overnight' => 398,
425
'hsa_wrist_temperature_data' => 409, # Message number for the HSA wrist temperature data message
426
'mfg_range_min' => 0xFF00, # 0xFF00 - 0xFFFE reserved for manufacturer specific messages
427
'mfg_range_max' => 0xFFFE,
428
},
429
430
'checksum' => +{
431
'_base_type' => FIT_UINT8,
432
'clear' => 0,
433
'ok' => 1,
434
},
435
436
'file_flags' => +{
437
'_base_type' => FIT_UINT8Z,
438
'_mask' => 1,
439
'read' => 0x02,
440
'write' => 0x04,
441
'erase' => 0x08,
442
},
443
444
'mesg_count' => +{
445
'_base_type' => FIT_ENUM,
446
'num_per_file' => 0,
447
'max_per_file' => 1,
448
'max_per_file_type' => 2,
449
},
450
451
'date_time' => +{
452
'_base_type' => FIT_UINT32,
453
'min' => 0x10000000,
454
'_min' => 0x10000000,
455
'_out_of_range' => 'seconds from device power on',
456
'_offset' => -timegm(0, 0, 0, 31, 11, 1989), # 1989-12-31 00:00:00 UTC
457
},
458
459
'local_date_time' => +{ # same as above, but in local time zone
460
'_base_type' => FIT_UINT32,
461
'min' => 0x10000000,
462
},
463
464
'message_index' => +{
465
'_base_type' => FIT_UINT16,
466
'_mask' => 1,
467
'selected' => 0x8000,
468
'reserved' => 0x7000,
469
'mask' => 0x0FFF,
470
},
471
472
'device_index' => +{ # dynamically created, as devices are added
473
'_base_type' => FIT_UINT8,
474
'creator' => 0, # creator of the file is always device index 0
475
'device1' => 1, # local, v6.00, garmin prod. edge520 (2067)
476
'device2' => 2, # local, v3.00, garmin prod. 1619
477
'heart_rate' => 3, # antplus
478
'speed' => 4, # antplus
479
'cadence' => 5, # antplus
480
'device6' => 6, # antplus power?
481
},
482
483
'gender' => +{
484
'_base_type' => FIT_ENUM,
485
'female' => 0,
486
'male' => 1,
487
},
488
489
'language' => +{
490
'_base_type' => FIT_ENUM,
491
'english' => 0,
492
'french' => 1,
493
'italian' => 2,
494
'german' => 3,
495
'spanish' => 4,
496
'croatian' => 5,
497
'czech' => 6,
498
'danish' => 7,
499
'dutch' => 8,
500
'finnish' => 9,
501
'greek' => 10,
502
'hungarian' => 11,
503
'norwegian' => 12,
504
'polish' => 13,
505
'portuguese' => 14,
506
'slovakian' => 15,
507
'slovenian' => 16,
508
'swedish' => 17,
509
'russian' => 18,
510
'turkish' => 19,
511
'latvian' => 20,
512
'ukrainian' => 21,
513
'arabic' => 22,
514
'farsi' => 23,
515
'bulgarian' => 24,
516
'romanian' => 25,
517
'chinese' => 26,
518
'japanese' => 27,
519
'korean' => 28,
520
'taiwanese' => 29,
521
'thai' => 30,
522
'hebrew' => 31,
523
'brazilian_portuguese' => 32,
524
'indonesian' => 33,
525
'malaysian' => 34,
526
'vietnamese' => 35,
527
'burmese' => 36,
528
'mongolian' => 37,
529
'custom' => 254,
530
},
531
532
'language_bits_0' => +{
533
'_base_type' => FIT_UINT8Z,
534
'english' => 0x01,
535
'french' => 0x02,
536
'italian' => 0x04,
537
'german' => 0x08,
538
'spanish' => 0x10,
539
'croatian' => 0x20,
540
'czech' => 0x40,
541
'danish' => 0x80,
542
},
543
544
'language_bits_1' => +{
545
'_base_type' => FIT_UINT8Z,
546
'dutch' => 0x01,
547
'finnish' => 0x02,
548
'greek' => 0x04,
549
'hungarian' => 0x08,
550
'norwegian' => 0x10,
551
'polish' => 0x20,
552
'portuguese' => 0x40,
553
'slovakian' => 0x80,
554
},
555
556
'language_bits_2' => +{
557
'_base_type' => FIT_UINT8Z,
558
'slovenian' => 0x01,
559
'swedish' => 0x02,
560
'russian' => 0x04,
561
'turkish' => 0x08,
562
'latvian' => 0x10,
563
'ukrainian' => 0x20,
564
'arabic' => 0x40,
565
'farsi' => 0x80,
566
},
567
568
'language_bits_3' => +{
569
'_base_type' => FIT_UINT8Z,
570
'bulgarian' => 0x01,
571
'romanian' => 0x02,
572
'chinese' => 0x04,
573
'japanese' => 0x08,
574
'korean' => 0x10,
575
'taiwanese' => 0x20,
576
'thai' => 0x40,
577
'hebrew' => 0x80,
578
},
579
580
'language_bits_4' => +{
581
'_base_type' => FIT_UINT8Z,
582
'brazilian_portuguese' => 0x01,
583
'indonesian' => 0x02,
584
'malaysian' => 0x04,
585
'vietnamese' => 0x08,
586
'burmese' => 0x10,
587
'mongolian' => 0x20,
588
},
589
590
'time_zone' => +{
591
'_base_type' => FIT_ENUM,
592
'almaty' => 0,
593
'bangkok' => 1,
594
'bombay' => 2,
595
'brasilia' => 3,
596
'cairo' => 4,
597
'cape_verde_is' => 5,
598
'darwin' => 6,
599
'eniwetok' => 7,
600
'fiji' => 8,
601
'hong_kong' => 9,
602
'islamabad' => 10,
603
'kabul' => 11,
604
'magadan' => 12,
605
'mid_atlantic' => 13,
606
'moscow' => 14,
607
'muscat' => 15,
608
'newfoundland' => 16,
609
'samoa' => 17,
610
'sydney' => 18,
611
'tehran' => 19,
612
'tokyo' => 20,
613
'us_alaska' => 21,
614
'us_atlantic' => 22,
615
'us_central' => 23,
616
'us_eastern' => 24,
617
'us_hawaii' => 25,
618
'us_mountain' => 26,
619
'us_pacific' => 27,
620
'other' => 28,
621
'auckland' => 29,
622
'kathmandu' => 30,
623
'europe_western_wet' => 31,
624
'europe_central_cet' => 32,
625
'europe_eastern_eet' => 33,
626
'jakarta' => 34,
627
'perth' => 35,
628
'adelaide' => 36,
629
'brisbane' => 37,
630
'tasmania' => 38,
631
'iceland' => 39,
632
'amsterdam' => 40,
633
'athens' => 41,
634
'barcelona' => 42,
635
'berlin' => 43,
636
'brussels' => 44,
637
'budapest' => 45,
638
'copenhagen' => 46,
639
'dublin' => 47,
640
'helsinki' => 48,
641
'lisbon' => 49,
642
'london' => 50,
643
'madrid' => 51,
644
'munich' => 52,
645
'oslo' => 53,
646
'paris' => 54,
647
'prague' => 55,
648
'reykjavik' => 56,
649
'rome' => 57,
650
'stockholm' => 58,
651
'vienna' => 59,
652
'warsaw' => 60,
653
'zurich' => 61,
654
'quebec' => 62,
655
'ontario' => 63,
656
'manitoba' => 64,
657
'saskatchewan' => 65,
658
'alberta' => 66,
659
'british_columbia' => 67,
660
'boise' => 68,
661
'boston' => 69,
662
'chicago' => 70,
663
'dallas' => 71,
664
'denver' => 72,
665
'kansas_city' => 73,
666
'las_vegas' => 74,
667
'los_angeles' => 75,
668
'miami' => 76,
669
'minneapolis' => 77,
670
'new_york' => 78,
671
'new_orleans' => 79,
672
'phoenix' => 80,
673
'santa_fe' => 81,
674
'seattle' => 82,
675
'washington_dc' => 83,
676
'us_arizona' => 84,
677
'chita' => 85,
678
'ekaterinburg' => 86,
679
'irkutsk' => 87,
680
'kaliningrad' => 88,
681
'krasnoyarsk' => 89,
682
'novosibirsk' => 90,
683
'petropavlovsk_kamchatskiy' => 91,
684
'samara' => 92,
685
'vladivostok' => 93,
686
'mexico_central' => 94,
687
'mexico_mountain' => 95,
688
'mexico_pacific' => 96,
689
'cape_town' => 97,
690
'winkhoek' => 98,
691
'lagos' => 99,
692
'riyahd' => 100,
693
'venezuela' => 101,
694
'australia_lh' => 102,
695
'santiago' => 103,
696
'manual' => 253,
697
'automatic' => 254,
698
},
699
700
'display_measure' => +{
701
'_base_type' => FIT_ENUM,
702
'metric' => 0,
703
'statute' => 1,
704
'nautical' => 2,
705
},
706
707
'display_heart' => +{
708
'_base_type' => FIT_ENUM,
709
'bpm' => 0,
710
'max' => 1,
711
'reserve' => 2,
712
},
713
714
'display_power' => +{
715
'_base_type' => FIT_ENUM,
716
'watts' => 0,
717
'percent_ftp' => 1,
718
},
719
720
'display_position' => +{
721
'_base_type' => FIT_ENUM,
722
'degree' => 0,
723
'degree_minute' => 1,
724
'degree_minute_second' => 2,
725
'austrian_grid' => 3,
726
'british_grid' => 4,
727
'dutch_grid' => 5,
728
'hungarian_grid' => 6,
729
'finnish_grid' => 7,
730
'german_grid' => 8,
731
'icelandic_grid' => 9,
732
'indonesian_equatorial' => 10,
733
'indonesian_irian' => 11,
734
'indonesian_southern' => 12,
735
'india_zone_0' => 13,
736
'india_zone_IA' => 14,
737
'india_zone_IB' => 15,
738
'india_zone_IIA' => 16,
739
'india_zone_IIB' => 17,
740
'india_zone_IIIA' => 18,
741
'india_zone_IIIB' => 19,
742
'india_zone_IVA' => 20,
743
'india_zone_IVB' => 21,
744
'irish_transverse' => 22,
745
'irish_grid' => 23,
746
'loran' => 24,
747
'maidenhead_grid' => 25,
748
'mgrs_grid' => 26,
749
'new_zealand_grid' => 27,
750
'new_zealand_transverse' => 28,
751
'qatar_grid' => 29,
752
'modified_swedish_grid' => 30,
753
'swedish_grid' => 31,
754
'south_african_grid' => 32,
755
'swiss_grid' => 33,
756
'taiwan_grid' => 34,
757
'united_states_grid' => 35,
758
'utm_ups_grid' => 36,
759
'west_malayan' => 37,
760
'borneo_rso' => 38,
761
'estonian_grid' => 39,
762
'latvian_grid' => 40,
763
'swedish_ref_99_grid' => 41,
764
},
765
766
'switch' => +{
767
'_base_type' => FIT_ENUM,
768
'off' => 0,
769
'on' => 1,
770
'auto' => 2,
771
},
772
773
'sport' => +{
774
'_base_type' => FIT_ENUM,
775
'generic' => 0,
776
'running' => 1,
777
'cycling' => 2,
778
'transition' => 3, # multisport transition
779
'fitness_equipment' => 4,
780
'swimming' => 5,
781
'basketball' => 6,
782
'soccer' => 7,
783
'tennis' => 8,
784
'american_football' => 9,
785
'training' => 10,
786
'walking' => 11,
787
'cross_country_skiing' => 12,
788
'alpine_skiing' => 13,
789
'snowboarding' => 14,
790
'rowing' => 15,
791
'mountaineering' => 16,
792
'hiking' => 17,
793
'multisport' => 18,
794
'paddling' => 19,
795
'flying' => 20,
796
'e_biking' => 21,
797
'motorcycling' => 22,
798
'boating' => 23,
799
'driving' => 24,
800
'golf' => 25,
801
'hang_gliding' => 26,
802
'horseback_riding' => 27,
803
'hunting' => 28,
804
'fishing' => 29,
805
'inline_skating' => 30,
806
'rock_climbing' => 31,
807
'sailing' => 32,
808
'ice_skating' => 33,
809
'sky_diving' => 34,
810
'snowshoeing' => 35,
811
'snowmobiling' => 36,
812
'stand_up_paddleboarding' => 37,
813
'surfing' => 38,
814
'wakeboarding' => 39,
815
'water_skiing' => 40,
816
'kayaking' => 41,
817
'rafting' => 42,
818
'windsurfing' => 43,
819
'kitesurfing' => 44,
820
'tactical' => 45,
821
'jumpmaster' => 46,
822
'boxing' => 47,
823
'floor_climbing' => 48,
824
'baseball' => 49,
825
'diving' => 53,
826
'hiit' => 62,
827
'racket' => 64,
828
'wheelchair_push_walk' => 65,
829
'wheelchair_push_run' => 66,
830
'meditation' => 67,
831
'disc_golf' => 69,
832
'cricket' => 71,
833
'rugby' => 72,
834
'hockey' => 73,
835
'lacrosse' => 74,
836
'volleyball' => 75,
837
'water_tubing' => 76,
838
'wakesurfing' => 77,
839
'mixed_martial_arts' => 80,
840
'snorkeling' => 82,
841
'dance' => 83,
842
'jump_rope' => 84,
843
'all' => 254, # All is for goals only to include all sports.
844
},
845
846
'sport_bits_0' => +{
847
'_base_type' => FIT_UINT8Z,
848
'generic' => 0x01,
849
'running' => 0x02,
850
'cycling' => 0x04,
851
'transition' => 0x08,
852
'fitness_equipment' => 0x10,
853
'swimming' => 0x20,
854
'basketball' => 0x40,
855
'soccer' => 0x80,
856
},
857
858
'sport_bits_1' => +{
859
'_base_type' => FIT_UINT8Z,
860
'tennis' => 0x01,
861
'american_football' => 0x02,
862
'training' => 0x04,
863
'walking' => 0x08,
864
'cross_country_skiing' => 0x10,
865
'alpine_skiing' => 0x20,
866
'snowboarding' => 0x40,
867
'rowing' => 0x80,
868
},
869
870
'sport_bits_2' => +{
871
'_base_type' => FIT_UINT8Z,
872
'mountaineering' => 0x01,
873
'hiking' => 0x02,
874
'multisport' => 0x04,
875
'paddling' => 0x08,
876
'flying' => 0x10,
877
'e_biking' => 0x20,
878
'motorcycling' => 0x40,
879
'boating' => 0x80,
880
},
881
882
'sport_bits_3' => +{
883
'_base_type' => FIT_UINT8Z,
884
'driving' => 0x01,
885
'golf' => 0x02,
886
'hang_gliding' => 0x04,
887
'horseback_riding' => 0x08,
888
'hunting' => 0x10,
889
'fishing' => 0x20,
890
'inline_skating' => 0x40,
891
'rock_climbing' => 0x80,
892
},
893
894
'sport_bits_4' => +{
895
'_base_type' => FIT_UINT8Z,
896
'sailing' => 0x01,
897
'ice_skating' => 0x02,
898
'sky_diving' => 0x04,
899
'snowshoeing' => 0x08,
900
'snowmobiling' => 0x10,
901
'stand_up_paddleboarding' => 0x20,
902
'surfing' => 0x40,
903
'wakeboarding' => 0x80,
904
},
905
906
'sport_bits_5' => +{
907
'_base_type' => FIT_UINT8Z,
908
'water_skiing' => 0x01,
909
'kayaking' => 0x02,
910
'rafting' => 0x04,
911
'windsurfing' => 0x08,
912
'kitesurfing' => 0x10,
913
'tactical' => 0x20,
914
'jumpmaster' => 0x40,
915
'boxing' => 0x80,
916
},
917
918
'sport_bits_6' => +{
919
'_base_type' => FIT_UINT8Z,
920
'floor_climbing' => 0x01,
921
},
922
923
'sub_sport' => +{
924
'_base_type' => FIT_ENUM,
925
'generic' => 0,
926
'treadmill' => 1, # run/fitness equipment
927
'street' => 2, # run
928
'trail' => 3, # run
929
'track' => 4, # run
930
'spin' => 5, # cycling
931
'indoor_cycling' => 6, # cycling/fitness equipment
932
'road' => 7, # cycling
933
'mountain' => 8, # cycling
934
'downhill' => 9, # cycling
935
'recumbent' => 10, # cycling
936
'cyclocross' => 11, # cycling
937
'hand_cycling' => 12, # cycling
938
'track_cycling' => 13, # cycling
939
'indoor_rowing' => 14, # fitness equipment
940
'elliptical' => 15, # fitness equipment
941
'stair_climbing' => 16, # fitness equipment
942
'lap_swimming' => 17, # swimming
943
'open_water' => 18, # swimming
944
'flexibility_training' => 19, # training
945
'strength_training' => 20, # training
946
'warm_up' => 21, # tennis
947
'match' => 22, # tennis
948
'exercise' => 23, # tennis
949
'challenge' => 24,
950
'indoor_skiing' => 25, # fitness equipment
951
'cardio_training' => 26, # training
952
'indoor_walking' => 27, # walking/fitness equipment
953
'e_bike_fitness' => 28, # e-biking
954
'bmx' => 29, # cycling
955
'casual_walking' => 30, # walking
956
'speed_walking' => 31, # walking
957
'bike_to_run_transition' => 32, # transition
958
'run_to_bike_transition' => 33, # transition
959
'swim_to_bike_transition' => 34, # transition
960
'atv' => 35, # motorcycling
961
'motocross' => 36, # motorcycling
962
'backcountry' => 37, # alpine skiing/snowboarding
963
'resort' => 38, # alpine skiing/snowboarding
964
'rc_drone' => 39, # flying
965
'wingsuit' => 40, # flying
966
'whitewater' => 41, # kayaking/rafting
967
'skate_skiing' => 42, # cross country skiing
968
'yoga' => 43, # training
969
'pilates' => 44, # fitness equipment
970
'indoor_running' => 45, # run/fitness equipment
971
'gravel_cycling' => 46, # cycling
972
'e_bike_mountain' => 47, # cycling
973
'commuting' => 48, # cycling
974
'mixed_surface' => 49, # cycling
975
'navigate' => 50,
976
'track_me' => 51,
977
'map' => 52,
978
'single_gas_diving' => 53, # Diving
979
'multi_gas_diving' => 54, # Diving
980
'gauge_diving' => 55, # Diving
981
'apnea_diving' => 56, # Diving
982
'apnea_hunting' => 57, # Diving
983
'virtual_activity' => 58,
984
'obstacle' => 59, # Used for events where participants run, crawl through mud, climb over walls, etc.
985
'breathing' => 62,
986
'sail_race' => 65, # Sailing
987
'ultra' => 67, # Ultramarathon
988
'indoor_climbing' => 68, # Climbing
989
'bouldering' => 69, # Climbing
990
'hiit' => 70, # High Intensity Interval Training
991
'amrap' => 73, # HIIT
992
'emom' => 74, # HIIT
993
'tabata' => 75, # HIIT
994
'pickleball' => 84, # Racket
995
'padel' => 85, # Racket
996
'indoor_wheelchair_walk' => 86,
997
'indoor_wheelchair_run' => 87,
998
'indoor_hand_cycling' => 88,
999
'squash' => 94,
1000
'badminton' => 95,
1001
'racquetball' => 96,
1002
'table_tennis' => 97,
1003
'fly_canopy' => 110, # Flying
1004
'fly_paraglide' => 111, # Flying
1005
'fly_paramotor' => 112, # Flying
1006
'fly_pressurized' => 113, # Flying
1007
'fly_navigate' => 114, # Flying
1008
'fly_timer' => 115, # Flying
1009
'fly_altimeter' => 116, # Flying
1010
'fly_wx' => 117, # Flying
1011
'fly_vfr' => 118, # Flying
1012
'fly_ifr' => 119, # Flying
1013
'all' => 254,
1014
},
1015
1016
'sport_event' => +{
1017
'_base_type' => FIT_ENUM,
1018
'uncategorized' => 0,
1019
'geocaching' => 1,
1020
'fitness' => 2,
1021
'recreation' => 3,
1022
'race' => 4,
1023
'special_event' => 5,
1024
'training' => 6,
1025
'transportation' => 7,
1026
'touring' => 8,
1027
},
1028
1029
'activity' => +{
1030
'_base_type' => FIT_ENUM,
1031
'manual' => 0,
1032
'auto_multi_sport' => 1,
1033
},
1034
1035
'intensity' => +{
1036
'_base_type' => FIT_ENUM,
1037
'active' => 0,
1038
'rest' => 1,
1039
'warmup' => 2,
1040
'cooldown' => 3,
1041
},
1042
1043
'session_trigger' => +{
1044
'_base_type' => FIT_ENUM,
1045
'activity_end' => 0,
1046
'manual' => 1,
1047
'auto_multi_sport' => 2,
1048
'fitness_equipment' => 3,
1049
},
1050
1051
'autolap_trigger' => +{
1052
'_base_type' => FIT_ENUM,
1053
'time' => 0,
1054
'distance' => 1,
1055
'position_start' => 2,
1056
'position_lap' => 3,
1057
'position_waypoint' => 4,
1058
'position_marked' => 5,
1059
'off' => 6,
1060
},
1061
1062
'lap_trigger' => +{
1063
'_base_type' => FIT_ENUM,
1064
'manual' => 0,
1065
'time' => 1,
1066
'distance' => 2,
1067
'position_start' => 3,
1068
'position_lap' => 4,
1069
'position_waypoint' => 5,
1070
'position_marked' => 6,
1071
'session_end' => 7,
1072
'fitness_equipment' => 8,
1073
},
1074
1075
'time_mode' => +{
1076
'_base_type' => FIT_ENUM,
1077
'hour12' => 0,
1078
'hour24' => 1,
1079
'military' => 2,
1080
'hour_12_with_seconds' => 3,
1081
'hour_24_with_seconds' => 4,
1082
'utc' => 5,
1083
},
1084
1085
'backlight_mode' => +{
1086
'_base_type' => FIT_ENUM,
1087
'off' => 0,
1088
'manual' => 1,
1089
'key_and_messages' => 2,
1090
'auto_brightness' => 3,
1091
'smart_notifications' => 4,
1092
'key_and_messages_night' => 5,
1093
'key_and_messages_and_smart_notifications' => 6,
1094
},
1095
1096
'date_mode' => +{
1097
'_base_type' => FIT_ENUM,
1098
'day_month' => 0,
1099
'month_day' => 1,
1100
},
1101
1102
'backlight_timeout' => +{
1103
'_base_type' => FIT_UINT8,
1104
'infinite' => 0,
1105
},
1106
1107
'event' => +{
1108
'_base_type' => FIT_ENUM,
1109
'timer' => 0,
1110
'workout' => 3,
1111
'workout_step' => 4,
1112
'power_down' => 5,
1113
'power_up' => 6,
1114
'off_course' => 7,
1115
'session' => 8,
1116
'lap' => 9,
1117
'course_point' => 10,
1118
'battery' => 11,
1119
'virtual_partner_pace' => 12,
1120
'hr_high_alert' => 13,
1121
'hr_low_alert' => 14,
1122
'speed_high_alert' => 15,
1123
'speed_low_alert' => 16,
1124
'cad_high_alert' => 17,
1125
'cad_low_alert' => 18,
1126
'power_high_alert' => 19,
1127
'power_low_alert' => 20,
1128
'recovery_hr' => 21,
1129
'battery_low' => 22,
1130
'time_duration_alert' => 23,
1131
'distance_duration_alert' => 24,
1132
'calorie_duration_alert' => 25,
1133
'activity' => 26,
1134
'fitness_equipment' => 27,
1135
'length' => 28,
1136
'user_marker' => 32,
1137
'sport_point' => 33,
1138
'calibration' => 36,
1139
'front_gear_change' => 42,
1140
'rear_gear_change' => 43,
1141
'rider_position_change' => 44,
1142
'elev_high_alert' => 45,
1143
'elev_low_alert' => 46,
1144
'comm_timeout' => 47,
1145
'auto_activity_detect' => 54, # marker
1146
'dive_alert' => 56, # marker
1147
'dive_gas_switched' => 57, # marker
1148
'tank_pressure_reserve' => 71, # marker
1149
'tank_pressure_critical' => 72, # marker
1150
'tank_lost' => 73, # marker
1151
'radar_threat_alert' => 75, # start/stop/marker
1152
'tank_battery_low' => 76, # marker
1153
'tank_pod_connected' => 81, # marker - tank pod has connected
1154
'tank_pod_disconnected' => 82, # marker - tank pod has lost connection
1155
},
1156
1157
'event_type' => +{
1158
'_base_type' => FIT_ENUM,
1159
'start' => 0,
1160
'stop' => 1,
1161
'consecutive_depreciated' => 2,
1162
'marker' => 3,
1163
'stop_all' => 4,
1164
'begin_depreciated' => 5,
1165
'end_depreciated' => 6,
1166
'end_all_depreciated' => 7,
1167
'stop_disable' => 8,
1168
'stop_disable_all' => 9,
1169
},
1170
1171
'timer_trigger' => +{
1172
'_base_type' => FIT_ENUM,
1173
'manual' => 0,
1174
'auto' => 1,
1175
'fitness_equipment' => 2,
1176
},
1177
1178
'fitness_equipment_state' => +{
1179
'_base_type' => FIT_ENUM,
1180
'ready' => 0,
1181
'in_use' => 1,
1182
'paused' => 2,
1183
'unknown' => 3,
1184
},
1185
1186
'tone' => +{
1187
'_base_type' => FIT_ENUM,
1188
'off' => 0,
1189
'tone' => 1,
1190
'vibrate' => 2,
1191
'tone_and_vibrate' => 3,
1192
},
1193
'autoscroll' => +{
1194
'_base_type' => FIT_ENUM,
1195
'none' => 0,
1196
'slow' => 1,
1197
'medium' => 2,
1198
'fast' => 3,
1199
},
1200
1201
'activity_class' => +{
1202
'_base_type' => FIT_ENUM,
1203
'_mask' => 1,
1204
'level' => 0x7f,
1205
'level_max' => 100,
1206
'athlete' => 0x80,
1207
},
1208
1209
'hr_zone_calc' => +{
1210
'_base_type' => FIT_ENUM,
1211
'custom' => 0,
1212
'percent_max_hr' => 1,
1213
'percent_hrr' => 2,
1214
'percent_lthr' => 3,
1215
},
1216
1217
'pwr_zone_calc' => +{
1218
'_base_type' => FIT_ENUM,
1219
'custom' => 0,
1220
'percent_ftp' => 1,
1221
},
1222
1223
'wkt_step_duration' => +{
1224
'_base_type' => FIT_ENUM,
1225
'time' => 0,
1226
'distance' => 1,
1227
'hr_less_than' => 2,
1228
'hr_greater_than' => 3,
1229
'calories' => 4,
1230
'open' => 5,
1231
'repeat_until_steps_cmplt' => 6,
1232
'repeat_until_time' => 7,
1233
'repeat_until_distance' => 8,
1234
'repeat_until_calories' => 9,
1235
'repeat_until_hr_less_than' => 10,
1236
'repeat_until_hr_greater_than' => 11,
1237
'repeat_until_power_less_than' => 12,
1238
'repeat_until_power_greater_than' => 13,
1239
'power_less_than' => 14,
1240
'power_greater_than' => 15,
1241
'training_peaks_tss' => 16,
1242
'repeat_until_power_last_lap_less_than' => 17,
1243
'repeat_until_max_power_last_lap_less_than' => 18,
1244
'power_3s_less_than' => 19,
1245
'power_10s_less_than' => 20,
1246
'power_30s_less_than' => 21,
1247
'power_3s_greater_than' => 22,
1248
'power_10s_greater_than' => 23,
1249
'power_30s_greater_than' => 24,
1250
'power_lap_less_than' => 25,
1251
'power_lap_greater_than' => 26,
1252
'repeat_until_training_peaks_tss' => 27,
1253
'repetition_time' => 28,
1254
'reps' => 29,
1255
'time_only' => 31,
1256
},
1257
1258
'wkt_step_target' => +{
1259
'_base_type' => FIT_ENUM,
1260
'speed' => 0,
1261
'heart_rate' => 1,
1262
'open' => 2,
1263
'cadence' => 3,
1264
'power' => 4,
1265
'grade' => 5,
1266
'resistance' => 6,
1267
'power_3s' => 7,
1268
'power_10s' => 8,
1269
'power_30s' => 9,
1270
'power_lap' => 10,
1271
'swim_stroke' => 11,
1272
'speed_lap' => 12,
1273
'heart_rate_lap' => 13,
1274
},
1275
1276
'goal' => +{
1277
'_base_type' => FIT_ENUM,
1278
'time' => 0,
1279
'distance' => 1,
1280
'calories' => 2,
1281
'frequency' => 3,
1282
'steps' => 4,
1283
'ascent' => 5,
1284
'active_minutes' => 6,
1285
},
1286
1287
'goal_recurrence' => +{
1288
'_base_type' => FIT_ENUM,
1289
'off' => 0,
1290
'daily' => 1,
1291
'weekly' => 2,
1292
'monthly' => 3,
1293
'yearly' => 4,
1294
'custom' => 5,
1295
},
1296
1297
'goal_source' => +{
1298
'_base_type' => FIT_ENUM,
1299
'auto' => 0,
1300
'community' => 1,
1301
'user' => 2,
1302
},
1303
1304
'schedule' => +{
1305
'_base_type' => FIT_ENUM,
1306
'workout' => 0,
1307
'course' => 1,
1308
},
1309
1310
'course_point' => +{
1311
'_base_type' => FIT_ENUM,
1312
'generic' => 0,
1313
'summit' => 1,
1314
'valley' => 2,
1315
'water' => 3,
1316
'food' => 4,
1317
'danger' => 5,
1318
'left' => 6,
1319
'right' => 7,
1320
'straight' => 8,
1321
'first_aid' => 9,
1322
'fourth_category' => 10,
1323
'third_category' => 11,
1324
'second_category' => 12,
1325
'first_category' => 13,
1326
'hors_category' => 14,
1327
'sprint' => 15,
1328
'left_fork' => 16,
1329
'right_fork' => 17,
1330
'middle_fork' => 18,
1331
'slight_left' => 19,
1332
'sharp_left' => 20,
1333
'slight_right' => 21,
1334
'sharp_right' => 22,
1335
'u_turn' => 23,
1336
'segment_start' => 24,
1337
'segment_end' => 25,
1338
},
1339
1340
'manufacturer' => +{
1341
'_base_type' => FIT_UINT16,
1342
'garmin' => 1,
1343
'garmin_fr405_antfs' => 2,
1344
'zephyr' => 3,
1345
'dayton' => 4,
1346
'idt' => 5,
1347
'srm' => 6,
1348
'quarq' => 7,
1349
'ibike' => 8,
1350
'saris' => 9,
1351
'spark_hk' => 10,
1352
'tanita' => 11,
1353
'echowell' => 12,
1354
'dynastream_oem' => 13,
1355
'nautilus' => 14,
1356
'dynastream' => 15,
1357
'timex' => 16,
1358
'metrigear' => 17,
1359
'xelic' => 18,
1360
'beurer' => 19,
1361
'cardiosport' => 20,
1362
'a_and_d' => 21,
1363
'hmm' => 22,
1364
'suunto' => 23,
1365
'thita_elektronik' => 24,
1366
'gpulse' => 25,
1367
'clean_mobile' => 26,
1368
'pedal_brain' => 27,
1369
'peaksware' => 28,
1370
'saxonar' => 29,
1371
'lemond_fitness' => 30,
1372
'dexcom' => 31,
1373
'wahoo_fitness' => 32,
1374
'octane_fitness' => 33,
1375
'archinoetics' => 34,
1376
'the_hurt_box' => 35,
1377
'citizen_systems' => 36,
1378
'magellan' => 37,
1379
'osynce' => 38,
1380
'holux' => 39,
1381
'concept2' => 40,
1382
'one_giant_leap' => 42,
1383
'ace_sensor' => 43,
1384
'brim_brothers' => 44,
1385
'xplova' => 45,
1386
'perception_digital' => 46,
1387
'bf1systems' => 47,
1388
'pioneer' => 48,
1389
'spantec' => 49,
1390
'metalogics' => 50,
1391
'4iiiis' => 51,
1392
'seiko_epson' => 52,
1393
'seiko_epson_oem' => 53,
1394
'ifor_powell' => 54,
1395
'maxwell_guider' => 55,
1396
'star_trac' => 56,
1397
'breakaway' => 57,
1398
'alatech_technology_ltd' => 58,
1399
'mio_technology_europe' => 59,
1400
'rotor' => 60,
1401
'geonaute' => 61,
1402
'id_bike' => 62,
1403
'specialized' => 63,
1404
'wtek' => 64,
1405
'physical_enterprises' => 65,
1406
'north_pole_engineering' => 66,
1407
'bkool' => 67,
1408
'cateye' => 68,
1409
'stages_cycling' => 69,
1410
'sigmasport' => 70,
1411
'tomtom' => 71,
1412
'peripedal' => 72,
1413
'wattbike' => 73,
1414
'moxy' => 76,
1415
'ciclosport' => 77,
1416
'powerbahn' => 78,
1417
'acorn_projects_aps' => 79,
1418
'lifebeam' => 80,
1419
'bontrager' => 81,
1420
'wellgo' => 82,
1421
'scosche' => 83,
1422
'magura' => 84,
1423
'woodway' => 85,
1424
'elite' => 86,
1425
'nielsen_kellerman' => 87,
1426
'dk_city' => 88,
1427
'tacx' => 89,
1428
'direction_technology' => 90,
1429
'magtonic' => 91,
1430
'1partcarbon' => 92,
1431
'inside_ride_technologies' => 93,
1432
'sound_of_motion' => 94,
1433
'stryd' => 95,
1434
'icg' => 96,
1435
'mipulse' => 97,
1436
'bsx_athletics' => 98,
1437
'look' => 99,
1438
'campagnolo_srl' => 100,
1439
'body_bike_smart' => 101,
1440
'praxisworks' => 102,
1441
'limits_technology' => 103,
1442
'topaction_technology' => 104,
1443
'cosinuss' => 105,
1444
'fitcare' => 106,
1445
'magene' => 107,
1446
'giant_manufacturing_co' => 108,
1447
'tigrasport' => 109,
1448
'salutron' => 110,
1449
'technogym' => 111,
1450
'bryton_sensors' => 112,
1451
'latitude_limited' => 113,
1452
'soaring_technology' => 114,
1453
'igpsport' => 115,
1454
'thinkrider' => 116,
1455
'gopher_sport' => 117,
1456
'waterrower' => 118,
1457
'orangetheory' => 119,
1458
'inpeak' => 120,
1459
'kinetic' => 121,
1460
'johnson_health_tech' => 122,
1461
'polar_electro' => 123,
1462
'seesense' => 124,
1463
'nci_technology' => 125,
1464
'iqsquare' => 126,
1465
'leomo' => 127,
1466
'ifit_com' => 128,
1467
'coros_byte' => 129,
1468
'versa_design' => 130,
1469
'chileaf' => 131,
1470
'cycplus' => 132,
1471
'gravaa_byte' => 133,
1472
'sigeyi' => 134,
1473
'coospo' => 135,
1474
'geoid' => 136,
1475
'bosch' => 137,
1476
'kyto' => 138,
1477
'kinetic_sports' => 139,
1478
'decathlon_byte' => 140,
1479
'tq_systems' => 141,
1480
'tag_heuer' => 142,
1481
'keiser_fitness' => 143,
1482
'zwift_byte' => 144,
1483
'porsche_ep' => 145,
1484
'blackbird' => 146,
1485
'meilan_byte' => 147,
1486
'ezon' => 148,
1487
'laisi' => 149,
1488
'myzone' => 150,
1489
'development' => 255,
1490
'healthandlife' => 257,
1491
'lezyne' => 258,
1492
'scribe_labs' => 259,
1493
'zwift' => 260,
1494
'watteam' => 261,
1495
'recon' => 262,
1496
'favero_electronics' => 263,
1497
'dynovelo' => 264,
1498
'strava' => 265,
1499
'precor' => 266,
1500
'bryton' => 267,
1501
'sram' => 268,
1502
'navman' => 269,
1503
'cobi' => 270,
1504
'spivi' => 271,
1505
'mio_magellan' => 272,
1506
'evesports' => 273,
1507
'sensitivus_gauge' => 274,
1508
'podoon' => 275,
1509
'life_time_fitness' => 276,
1510
'falco_e_motors' => 277,
1511
'minoura' => 278,
1512
'cycliq' => 279,
1513
'luxottica' => 280,
1514
'trainer_road' => 281,
1515
'the_sufferfest' => 282,
1516
'fullspeedahead' => 283,
1517
'virtualtraining' => 284,
1518
'feedbacksports' => 285,
1519
'omata' => 286,
1520
'vdo' => 287,
1521
'magneticdays' => 288,
1522
'hammerhead' => 289,
1523
'kinetic_by_kurt' => 290,
1524
'shapelog' => 291,
1525
'dabuziduo' => 292,
1526
'jetblack' => 293,
1527
'coros' => 294,
1528
'virtugo' => 295,
1529
'velosense' => 296,
1530
'cycligentinc' => 297,
1531
'trailforks' => 298,
1532
'mahle_ebikemotion' => 299,
1533
'nurvv' => 300,
1534
'microprogram' => 301,
1535
'zone5cloud' => 302,
1536
'greenteg' => 303,
1537
'yamaha_motors' => 304,
1538
'whoop' => 305,
1539
'gravaa' => 306,
1540
'onelap' => 307,
1541
'monark_exercise' => 308,
1542
'form' => 309,
1543
'decathlon' => 310,
1544
'syncros' => 311,
1545
'heatup' => 312,
1546
'cannondale' => 313,
1547
'true_fitness' => 314,
1548
'RGT_cycling' => 315,
1549
'vasa' => 316,
1550
'race_republic' => 317,
1551
'fazua' => 318,
1552
'oreka_training' => 319,
1553
'lsec' => 320, # Lishun Electric & Communication
1554
'lululemon_studio' => 321,
1555
'shanyue' => 322,
1556
'spinning_mda' => 323,
1557
'hilldating' => 324,
1558
'aero_sensor' => 325,
1559
'nike' => 326,
1560
'magicshine' => 327,
1561
'ictrainer' => 328,
1562
'absolute_cycling' => 329,
1563
'actigraphcorp' => 5759,
1564
},
1565
1566
'garmin_product' => +{
1567
'_base_type' => FIT_UINT16,
1568
'hrm1' => 1,
1569
'axh01' => 2, # AXH01 HRM chipset
1570
'axb01' => 3,
1571
'axb02' => 4,
1572
'hrm2ss' => 5,
1573
'dsi_alf02' => 6,
1574
'hrm3ss' => 7,
1575
'hrm_run_single_byte_product_id' => 8, # hrm_run model for HRM ANT+ messaging
1576
'bsm' => 9, # BSM model for ANT+ messaging
1577
'bcm' => 10, # BCM model for ANT+ messaging
1578
'axs01' => 11, # AXS01 HRM Bike Chipset model for ANT+ messaging
1579
'hrm_tri_single_byte_product_id' => 12, # hrm_tri model for HRM ANT+ messaging
1580
'hrm4_run_single_byte_product_id' => 13, # hrm4 run model for HRM ANT+ messaging
1581
'fr225_single_byte_product_id' => 14, # fr225 model for HRM ANT+ messaging
1582
'gen3_bsm_single_byte_product_id' => 15, # gen3_bsm model for Bike Speed ANT+ messaging
1583
'gen3_bcm_single_byte_product_id' => 16, # gen3_bcm model for Bike Cadence ANT+ messaging
1584
'hrm_fit_single_byte_product_id' => 22,
1585
'OHR' => 255, # Garmin Wearable Optical Heart Rate Sensor for ANT+ HR Profile Broadcasting
1586
'fr301_china' => 473,
1587
'fr301_japan' => 474,
1588
'fr301_korea' => 475,
1589
'fr301_taiwan' => 494,
1590
'fr405' => 717, # Forerunner 405
1591
'fr50' => 782, # Forerunner 50
1592
'fr405_japan' => 987,
1593
'fr60' => 988, # Forerunner 60
1594
'dsi_alf01' => 1011,
1595
'fr310xt' => 1018, # Forerunner 310
1596
'edge500' => 1036,
1597
'fr110' => 1124, # Forerunner 110
1598
'edge800' => 1169,
1599
'edge500_taiwan' => 1199,
1600
'edge500_japan' => 1213,
1601
'chirp' => 1253,
1602
'fr110_japan' => 1274,
1603
'edge200' => 1325,
1604
'fr910xt' => 1328,
1605
'edge800_taiwan' => 1333,
1606
'edge800_japan' => 1334,
1607
'alf04' => 1341,
1608
'fr610' => 1345,
1609
'fr210_japan' => 1360,
1610
'vector_ss' => 1380,
1611
'vector_cp' => 1381,
1612
'edge800_china' => 1386,
1613
'edge500_china' => 1387,
1614
'approach_g10' => 1405,
1615
'fr610_japan' => 1410,
1616
'edge500_korea' => 1422,
1617
'fr70' => 1436,
1618
'fr310xt_4t' => 1446,
1619
'amx' => 1461,
1620
'fr10' => 1482,
1621
'edge800_korea' => 1497,
1622
'swim' => 1499,
1623
'fr910xt_china' => 1537,
1624
'fenix' => 1551,
1625
'edge200_taiwan' => 1555,
1626
'edge510' => 1561,
1627
'edge810' => 1567,
1628
'tempe' => 1570,
1629
'fr910xt_japan' => 1600,
1630
'fr620' => 1623,
1631
'fr220' => 1632,
1632
'fr910xt_korea' => 1664,
1633
'fr10_japan' => 1688,
1634
'edge810_japan' => 1721,
1635
'virb_elite' => 1735,
1636
'edge_touring' => 1736, # Also Edge Touring Plus
1637
'edge510_japan' => 1742,
1638
'hrm_tri' => 1743, # Also HRM-Swim
1639
'hrm_run' => 1752,
1640
'fr920xt' => 1765,
1641
'edge510_asia' => 1821,
1642
'edge810_china' => 1822,
1643
'edge810_taiwan' => 1823,
1644
'edge1000' => 1836,
1645
'vivo_fit' => 1837,
1646
'virb_remote' => 1853,
1647
'vivo_ki' => 1885,
1648
'fr15' => 1903,
1649
'vivo_active' => 1907,
1650
'edge510_korea' => 1918,
1651
'fr620_japan' => 1928,
1652
'fr620_china' => 1929,
1653
'fr220_japan' => 1930,
1654
'fr220_china' => 1931,
1655
'approach_s6' => 1936,
1656
'vivo_smart' => 1956,
1657
'fenix2' => 1967,
1658
'epix' => 1988,
1659
'fenix3' => 2050,
1660
'edge1000_taiwan' => 2052,
1661
'edge1000_japan' => 2053,
1662
'fr15_japan' => 2061,
1663
'edge520' => 2067,
1664
'edge1000_china' => 2070,
1665
'fr620_russia' => 2072,
1666
'fr220_russia' => 2073,
1667
'vector_s' => 2079,
1668
'edge1000_korea' => 2100,
1669
'fr920xt_taiwan' => 2130,
1670
'fr920xt_china' => 2131,
1671
'fr920xt_japan' => 2132,
1672
'virbx' => 2134,
1673
'vivo_smart_apac' => 2135,
1674
'etrex_touch' => 2140,
1675
'edge25' => 2147,
1676
'fr25' => 2148,
1677
'vivo_fit2' => 2150,
1678
'fr225' => 2153,
1679
'fr630' => 2156,
1680
'fr230' => 2157,
1681
'fr735xt' => 2158,
1682
'vivo_active_apac' => 2160,
1683
'vector_2' => 2161,
1684
'vector_2s' => 2162,
1685
'virbxe' => 2172,
1686
'fr620_taiwan' => 2173,
1687
'fr220_taiwan' => 2174,
1688
'truswing' => 2175,
1689
'd2airvenu' => 2187,
1690
'fenix3_china' => 2188,
1691
'fenix3_twn' => 2189,
1692
'varia_headlight' => 2192,
1693
'varia_taillight_old' => 2193,
1694
'edge_explore_1000' => 2204,
1695
'fr225_asia' => 2219,
1696
'varia_radar_taillight' => 2225,
1697
'varia_radar_display' => 2226,
1698
'edge20' => 2238,
1699
'edge520_asia' => 2260,
1700
'edge520_japan' => 2261,
1701
'd2_bravo' => 2262,
1702
'approach_s20' => 2266,
1703
'vivo_smart2' => 2271,
1704
'edge1000_thai' => 2274,
1705
'varia_remote' => 2276,
1706
'edge25_asia' => 2288,
1707
'edge25_jpn' => 2289,
1708
'edge20_asia' => 2290,
1709
'approach_x40' => 2292,
1710
'fenix3_japan' => 2293,
1711
'vivo_smart_emea' => 2294,
1712
'fr630_asia' => 2310,
1713
'fr630_jpn' => 2311,
1714
'fr230_jpn' => 2313,
1715
'hrm4_run' => 2327,
1716
'epix_japan' => 2332,
1717
'vivo_active_hr' => 2337,
1718
'vivo_smart_gps_hr' => 2347,
1719
'vivo_smart_hr' => 2348,
1720
'vivo_smart_hr_asia' => 2361,
1721
'vivo_smart_gps_hr_asia' => 2362,
1722
'vivo_move' => 2368,
1723
'varia_taillight' => 2379,
1724
'fr235_asia' => 2396,
1725
'fr235_japan' => 2397,
1726
'varia_vision' => 2398,
1727
'vivo_fit3' => 2406,
1728
'fenix3_korea' => 2407,
1729
'fenix3_sea' => 2408,
1730
'fenix3_hr' => 2413,
1731
'virb_ultra_30' => 2417,
1732
'index_smart_scale' => 2429,
1733
'fr235' => 2431,
1734
'fenix3_chronos' => 2432,
1735
'oregon7xx' => 2441,
1736
'rino7xx' => 2444,
1737
'epix_korea' => 2457,
1738
'fenix3_hr_chn' => 2473,
1739
'fenix3_hr_twn' => 2474,
1740
'fenix3_hr_jpn' => 2475,
1741
'fenix3_hr_sea' => 2476,
1742
'fenix3_hr_kor' => 2477,
1743
'nautix' => 2496,
1744
'vivo_active_hr_apac' => 2497,
1745
'fr35' => 2503,
1746
'oregon7xx_ww' => 2512,
1747
'edge_820' => 2530,
1748
'edge_explore_820' => 2531,
1749
'fr735xt_apac' => 2533,
1750
'fr735xt_japan' => 2534,
1751
'fenix5s' => 2544,
1752
'd2_bravo_titanium' => 2547,
1753
'varia_ut800' => 2567, # Varia UT 800 SW
1754
'running_dynamics_pod' => 2593,
1755
'edge_820_china' => 2599,
1756
'edge_820_japan' => 2600,
1757
'fenix5x' => 2604,
1758
'vivo_fit_jr' => 2606,
1759
'vivo_smart3' => 2622,
1760
'vivo_sport' => 2623,
1761
'edge_820_taiwan' => 2628,
1762
'edge_820_korea' => 2629,
1763
'edge_820_sea' => 2630,
1764
'fr35_hebrew' => 2650,
1765
'approach_s60' => 2656,
1766
'fr35_apac' => 2667,
1767
'fr35_japan' => 2668,
1768
'fenix3_chronos_asia' => 2675,
1769
'virb_360' => 2687,
1770
'fr935' => 2691,
1771
'fenix5' => 2697,
1772
'vivoactive3' => 2700,
1773
'fr235_china_nfc' => 2733,
1774
'foretrex_601_701' => 2769,
1775
'vivo_move_hr' => 2772,
1776
'edge_1030' => 2713,
1777
'fr35_sea' => 2727,
1778
'vector_3' => 2787,
1779
'fenix5_asia' => 2796,
1780
'fenix5s_asia' => 2797,
1781
'fenix5x_asia' => 2798,
1782
'approach_z80' => 2806,
1783
'fr35_korea' => 2814,
1784
'd2charlie' => 2819,
1785
'vivo_smart3_apac' => 2831,
1786
'vivo_sport_apac' => 2832,
1787
'fr935_asia' => 2833,
1788
'descent' => 2859,
1789
'vivo_fit4' => 2878,
1790
'fr645' => 2886,
1791
'fr645m' => 2888,
1792
'fr30' => 2891,
1793
'fenix5s_plus' => 2900,
1794
'Edge_130' => 2909,
1795
'edge_1030_asia' => 2924,
1796
'vivosmart_4' => 2927,
1797
'vivo_move_hr_asia' => 2945,
1798
'approach_x10' => 2962,
1799
'fr30_asia' => 2977,
1800
'vivoactive3m_w' => 2988,
1801
'fr645_asia' => 3003,
1802
'fr645m_asia' => 3004,
1803
'edge_explore' => 3011,
1804
'gpsmap66' => 3028,
1805
'approach_s10' => 3049,
1806
'vivoactive3m_l' => 3066,
1807
'approach_g80' => 3085,
1808
'edge_130_asia' => 3092,
1809
'edge_1030_bontrager' => 3095,
1810
'fenix5_plus' => 3110,
1811
'fenix5x_plus' => 3111,
1812
'edge_520_plus' => 3112,
1813
'fr945' => 3113,
1814
'edge_530' => 3121,
1815
'edge_830' => 3122,
1816
'instinct_esports' => 3126,
1817
'fenix5s_plus_apac' => 3134,
1818
'fenix5x_plus_apac' => 3135,
1819
'edge_520_plus_apac' => 3142,
1820
'descent_t1' => 3143,
1821
'fr235l_asia' => 3144,
1822
'fr245_asia' => 3145,
1823
'vivo_active3m_apac' => 3163,
1824
'gen3_bsm' => 3192, # gen3 bike speed sensor
1825
'gen3_bcm' => 3193, # gen3 bike cadence sensor
1826
'vivo_smart4_asia' => 3218,
1827
'vivoactive4_small' => 3224,
1828
'vivoactive4_large' => 3225,
1829
'venu' => 3226,
1830
'marq_driver' => 3246,
1831
'marq_aviator' => 3247,
1832
'marq_captain' => 3248,
1833
'marq_commander' => 3249,
1834
'marq_expedition' => 3250,
1835
'marq_athlete' => 3251,
1836
'descent_mk2' => 3258,
1837
'gpsmap66i' => 3284,
1838
'fenix6S_sport' => 3287,
1839
'fenix6S' => 3288,
1840
'fenix6_sport' => 3289,
1841
'fenix6' => 3290,
1842
'fenix6x' => 3291,
1843
'hrm_dual' => 3299, # HRM-Dual
1844
'hrm_pro' => 3300, # HRM-Pro
1845
'vivo_move3_premium' => 3308,
1846
'approach_s40' => 3314,
1847
'fr245m_asia' => 3321,
1848
'edge_530_apac' => 3349,
1849
'edge_830_apac' => 3350,
1850
'vivo_move3' => 3378,
1851
'vivo_active4_small_asia' => 3387,
1852
'vivo_active4_large_asia' => 3388,
1853
'vivo_active4_oled_asia' => 3389,
1854
'swim2' => 3405,
1855
'marq_driver_asia' => 3420,
1856
'marq_aviator_asia' => 3421,
1857
'vivo_move3_asia' => 3422,
1858
'fr945_asia' => 3441,
1859
'vivo_active3t_chn' => 3446,
1860
'marq_captain_asia' => 3448,
1861
'marq_commander_asia' => 3449,
1862
'marq_expedition_asia' => 3450,
1863
'marq_athlete_asia' => 3451,
1864
'instinct_solar' => 3466,
1865
'fr45_asia' => 3469,
1866
'vivoactive3_daimler' => 3473,
1867
'legacy_rey' => 3498,
1868
'legacy_darth_vader' => 3499,
1869
'legacy_captain_marvel' => 3500,
1870
'legacy_first_avenger' => 3501,
1871
'fenix6s_sport_asia' => 3512,
1872
'fenix6s_asia' => 3513,
1873
'fenix6_sport_asia' => 3514,
1874
'fenix6_asia' => 3515,
1875
'fenix6x_asia' => 3516,
1876
'legacy_captain_marvel_asia' => 3535,
1877
'legacy_first_avenger_asia' => 3536,
1878
'legacy_rey_asia' => 3537,
1879
'legacy_darth_vader_asia' => 3538,
1880
'descent_mk2s' => 3542,
1881
'edge_130_plus' => 3558,
1882
'edge_1030_plus' => 3570,
1883
'rally_200' => 3578, # Rally 100/200 Power Meter Series
1884
'fr745' => 3589,
1885
'venusq' => 3600,
1886
'lily' => 3615,
1887
'marq_adventurer' => 3624,
1888
'enduro' => 3638,
1889
'swim2_apac' => 3639,
1890
'marq_adventurer_asia' => 3648,
1891
'fr945_lte' => 3652,
1892
'descent_mk2_asia' => 3702, # Mk2 and Mk2i
1893
'venu2' => 3703,
1894
'venu2s' => 3704,
1895
'venu_daimler_asia' => 3737,
1896
'marq_golfer' => 3739,
1897
'venu_daimler' => 3740,
1898
'fr745_asia' => 3794,
1899
'varia_rct715' => 3808,
1900
'lily_asia' => 3809,
1901
'edge_1030_plus_asia' => 3812,
1902
'edge_130_plus_asia' => 3813,
1903
'approach_s12' => 3823,
1904
'enduro_asia' => 3872,
1905
'venusq_asia' => 3837,
1906
'edge_1040' => 3843,
1907
'marq_golfer_asia' => 3850,
1908
'venu2_plus' => 3851,
1909
'gnss' => 3865,
1910
'fr55' => 3869,
1911
'instinct_2' => 3888,
1912
'fenix7s' => 3905,
1913
'fenix7' => 3906,
1914
'fenix7x' => 3907,
1915
'fenix7s_apac' => 3908,
1916
'fenix7_apac' => 3909,
1917
'fenix7x_apac' => 3910,
1918
'approach_g12' => 3927,
1919
'descent_mk2s_asia' => 3930,
1920
'approach_s42' => 3934,
1921
'epix_gen2' => 3943,
1922
'epix_gen2_apac' => 3944,
1923
'venu2s_asia' => 3949,
1924
'venu2_asia' => 3950,
1925
'fr945_lte_asia' => 3978,
1926
'vivo_move_sport' => 3982,
1927
'vivomove_trend' => 3983,
1928
'approach_S12_asia' => 3986,
1929
'fr255_music' => 3990,
1930
'fr255_small_music' => 3991,
1931
'fr255' => 3992,
1932
'fr255_small' => 3993,
1933
'approach_g12_asia' => 4001,
1934
'approach_s42_asia' => 4002,
1935
'descent_g1' => 4005,
1936
'venu2_plus_asia' => 4017,
1937
'fr955' => 4024,
1938
'fr55_asia' => 4033,
1939
'edge_540' => 4061,
1940
'edge_840' => 4062,
1941
'vivosmart_5' => 4063,
1942
'instinct_2_asia' => 4071,
1943
'marq_gen2' => 4105, # Adventurer, Athlete, Captain, Golfer
1944
'venusq2' => 4115,
1945
'venusq2music' => 4116,
1946
'marq_gen2_aviator' => 4124,
1947
'd2_air_x10' => 4125,
1948
'hrm_pro_plus' => 4130,
1949
'descent_g1_asia' => 4132,
1950
'tactix7' => 4135,
1951
'instinct_crossover' => 4155,
1952
'edge_explore2' => 4169,
1953
'descent_mk3' => 4222,
1954
'descent_mk3i' => 4223,
1955
'approach_s70' => 4233,
1956
'fr265_large' => 4257,
1957
'fr265_small' => 4258,
1958
'venu3' => 4260,
1959
'venu3s' => 4261,
1960
'tacx_neo_smart' => 4265, # Neo Smart, Tacx
1961
'tacx_neo2_smart' => 4266, # Neo 2 Smart, Tacx
1962
'tacx_neo2_t_smart' => 4267, # Neo 2T Smart, Tacx
1963
'tacx_neo_smart_bike' => 4268, # Neo Smart Bike, Tacx
1964
'tacx_satori_smart' => 4269, # Satori Smart, Tacx
1965
'tacx_flow_smart' => 4270, # Flow Smart, Tacx
1966
'tacx_vortex_smart' => 4271, # Vortex Smart, Tacx
1967
'tacx_bushido_smart' => 4272, # Bushido Smart, Tacx
1968
'tacx_genius_smart' => 4273, # Genius Smart, Tacx
1969
'tacx_flux_flux_s_smart' => 4274, # Flux/Flux S Smart, Tacx
1970
'tacx_flux2_smart' => 4275, # Flux 2 Smart, Tacx
1971
'tacx_magnum' => 4276, # Magnum, Tacx
1972
'edge_1040_asia' => 4305,
1973
'epix_gen2_pro_42' => 4312,
1974
'epix_gen2_pro_47' => 4313,
1975
'epix_gen2_pro_51' => 4314,
1976
'fr965' => 4315,
1977
'enduro2' => 4341,
1978
'fenix7s_pro_solar' => 4374,
1979
'fenix7_pro_solar' => 4375,
1980
'fenix7x_pro_solar' => 4376,
1981
'lily2' => 4380,
1982
'instinct_2x' => 4394,
1983
'vivoactive5' => 4426,
1984
'fr165' => 4432,
1985
'fr165_music' => 4433,
1986
'descent_t2' => 4442,
1987
'hrm_fit' => 4446,
1988
'marq_gen2_commander' => 4472,
1989
'd2_mach1_pro' => 4556,
1990
'sdm4' => 10007, # SDM4 footpod
1991
'edge_remote' => 10014,
1992
'tacx_training_app_win' => 20533,
1993
'tacx_training_app_mac' => 20534,
1994
'tacx_training_app_mac_catalyst' => 20565,
1995
'training_center' => 20119,
1996
'tacx_training_app_android' => 30045,
1997
'tacx_training_app_ios' => 30046,
1998
'tacx_training_app_legacy' => 30047,
1999
'connectiq_simulator' => 65531,
2000
'android_antplus_plugin' => 65532,
2001
'connect' => 65534, # Garmin Connect website
2002
},
2003
2004
'device_type' => +{
2005
'_moved_to' => 'antplus_device_type',
2006
},
2007
2008
'antplus_device_type' => +{
2009
'_base_type' => FIT_UINT8,
2010
'antfs' => 1,
2011
'bike_power' => 11,
2012
'environment_sensor_legacy' => 12,
2013
'multi_sport_speed_distance' => 15,
2014
'control' => 16,
2015
'fitness_equipment' => 17,
2016
'blood_pressure' => 18,
2017
'geocache_node' => 19,
2018
'light_electric_vehicle' => 20,
2019
'env_sensor' => 25,
2020
'racquet' => 26,
2021
'control_hub' => 27,
2022
'muscle_oxygen' => 31,
2023
'shifting' => 34,
2024
'bike_light_main' => 35,
2025
'bike_light_shared' => 36,
2026
'exd' => 38,
2027
'bike_radar' => 40,
2028
'bike_aero' => 46,
2029
'weight_scale' => 119,
2030
'heart_rate' => 120,
2031
'bike_speed_cadence' => 121,
2032
'bike_cadence' => 122,
2033
'bike_speed' => 123,
2034
'stride_speed_distance' => 124,
2035
},
2036
2037
'ant_network' => +{
2038
'_base_type' => FIT_ENUM,
2039
'public' => 0,
2040
'antplus' => 1,
2041
'antfs' => 2,
2042
'private' => 3,
2043
},
2044
2045
'workout_capabilities' => +{
2046
'_base_type' => FIT_UINT32Z,
2047
'_mask' => 1,
2048
'interval' => 0x00000001,
2049
'custom' => 0x00000002,
2050
'fitness_equipment' => 0x00000004,
2051
'firstbeat' => 0x00000008,
2052
'new_leaf' => 0x00000010,
2053
'tcx' => 0x00000020,
2054
'speed' => 0x00000080,
2055
'heart_rate' => 0x00000100,
2056
'distance' => 0x00000200,
2057
'cadence' => 0x00000400,
2058
'power' => 0x00000800,
2059
'grade' => 0x00001000,
2060
'resistance' => 0x00002000,
2061
'protected' => 0x00004000,
2062
},
2063
2064
'battery_status' => +{
2065
'_base_type' => FIT_UINT8,
2066
'new' => 1,
2067
'good' => 2,
2068
'ok' => 3,
2069
'low' => 4,
2070
'critical' => 5,
2071
'charging' => 6,
2072
'unknown' => 7,
2073
},
2074
2075
'hr_type' => +{
2076
'_base_type' => FIT_ENUM,
2077
'normal' => 0,
2078
'irregular' => 1,
2079
},
2080
2081
'course_capabilities' => +{
2082
'_base_type' => FIT_UINT32Z,
2083
'_mask' => 1,
2084
'processed' => 0x00000001,
2085
'valid' => 0x00000002,
2086
'time' => 0x00000004,
2087
'distance' => 0x00000008,
2088
'position' => 0x00000010,
2089
'heart_rate' => 0x00000020,
2090
'power' => 0x00000040,
2091
'cadence' => 0x00000080,
2092
'training' => 0x00000100,
2093
'navigation' => 0x00000200,
2094
'bikeway' => 0x00000400,
2095
'aviation'=> 0x00001000, # Denote course files to be used as flight plans
2096
},
2097
2098
'weight' => +{
2099
'_base_type' => FIT_UINT16,
2100
'calculating' => 0xFFFE,
2101
},
2102
2103
'workout_hr' => +{
2104
'_base_type' => FIT_UINT32,
2105
'bpm_offset' => 100,
2106
},
2107
2108
'workout_power' => +{
2109
'_base_type' => FIT_UINT32,
2110
'watts_offset' => 1000,
2111
},
2112
2113
'bp_status' => +{
2114
'_base_type' => FIT_ENUM,
2115
'no_error' => 0,
2116
'error_incomplete_data' => 1,
2117
'error_no_measurement' => 2,
2118
'error_data_out_of_range' => 3,
2119
'error_irregular_heart_rate' => 4,
2120
},
2121
2122
'user_local_id' => +{
2123
'_base_type' => FIT_UINT16,
2124
'local_min' => 0x0001,
2125
'local_max' => 0x000F,
2126
'stationary_min' => 0x0010,
2127
'stationary_max' => 0x00FF,
2128
'portable_min' => 0x0100,
2129
'portable_max' => 0xFFFE,
2130
},
2131
2132
'swim_stroke' => +{
2133
'_base_type' => FIT_ENUM,
2134
'freestyle' => 0,
2135
'backstroke' => 1,
2136
'breaststroke' => 2,
2137
'butterfly' => 3,
2138
'drill' => 4,
2139
'mixed' => 5,
2140
'im' => 6,
2141
},
2142
2143
'activity_type' => +{
2144
'_base_type' => FIT_ENUM,
2145
'generic' => 0,
2146
'running' => 1,
2147
'cycling' => 2,
2148
'transition' => 3,
2149
'fitness_equipment' => 4,
2150
'swimming' => 5,
2151
'walking' => 6,
2152
'sedentary' => 8,
2153
'all' => 254,
2154
},
2155
2156
'activity_subtype' => +{
2157
'_base_type' => FIT_ENUM,
2158
'generic' => 0,
2159
'treadmill' => 1, # run
2160
'street' => 2, # run
2161
'trail' => 3, # run
2162
'track' => 4, # run
2163
'spin' => 5, # cycling
2164
'indoor_cycling' => 6, # cycling
2165
'road' => 7, # cycling
2166
'mountain' => 8, # cycling
2167
'downhill' => 9, # cycling
2168
'recumbent' => 10, # cycling
2169
'cyclocross' => 11, # cycling
2170
'hand_cycling' => 12, # cycling
2171
'track_cycling' => 13, # cycling
2172
'indoor_rowing' => 14, # fitness equipment
2173
'elliptical' => 15, # fitness equipment
2174
'stair_climbing' => 16, # fitness equipment
2175
'lap_swimming' => 17, # swimming
2176
'open_water' => 18, # swimming
2177
'all' => 254,
2178
},
2179
2180
'activity_level' => +{
2181
'_base_type' => FIT_ENUM,
2182
'low' => 0,
2183
'medium' => 1,
2184
'high' => 2,
2185
},
2186
2187
'side' => +{
2188
'_base_type' => FIT_ENUM,
2189
'right' => 0,
2190
'left' => 1,
2191
},
2192
2193
'left_right_balance' => +{
2194
'_base_type' => FIT_UINT8,
2195
'mask' => 0x7F,
2196
'right' => 0x80,
2197
},
2198
2199
'left_right_balance_100' => +{
2200
'_base_type' => FIT_UINT16,
2201
'mask' => 0x3FFF,
2202
'right' => 0x8000,
2203
},
2204
2205
'length_type' => +{
2206
'_base_type' => FIT_ENUM,
2207
'idle' => 0,
2208
'active' => 1,
2209
},
2210
2211
'day_of_week' => +{
2212
'_base_type' => FIT_ENUM,
2213
'sunday' => 0,
2214
'monday' => 1,
2215
'tuesday' => 2,
2216
'wednesday' => 3,
2217
'thursday' => 4,
2218
'friday' => 5,
2219
'saturday' => 6,
2220
},
2221
2222
'connectivity_capabilities' => +{
2223
'_base_type' => FIT_UINT32Z,
2224
'bluetooth' => 0x00000001,
2225
'bluetooth_le' => 0x00000002,
2226
'ant' => 0x00000004,
2227
'activity_upload' => 0x00000008,
2228
'course_download' => 0x00000010,
2229
'workout_download' => 0x00000020,
2230
'live_track' => 0x00000040,
2231
'weather_conditions' => 0x00000080,
2232
'weather_alerts' => 0x00000100,
2233
'gps_ephemeris_download' => 0x00000200,
2234
'explicit_archive' => 0x00000400,
2235
'setup_incomplete' => 0x00000800,
2236
'continue_sync_after_software_update' => 0x00001000,
2237
'connect_iq_app_download' => 0x00002000,
2238
'golf_course_download' => 0x00004000,
2239
'device_initiates_sync' => 0x00008000,
2240
'connect_iq_watch_app_download' => 0x00010000,
2241
'connect_iq_widget_download' => 0x00020000,
2242
'connect_iq_watch_face_download' => 0x00040000,
2243
'connect_iq_data_field_download' => 0x00080000,
2244
'connect_iq_app_managment' => 0x00100000,
2245
'swing_sensor' => 0x00200000,
2246
'swing_sensor_remote' => 0x00400000,
2247
'incident_detection' => 0x00800000,
2248
'audio_prompts' => 0x01000000,
2249
'wifi_verification' => 0x02000000,
2250
'true_up' => 0x04000000,
2251
'find_my_watch' => 0x08000000,
2252
'remote_manual_sync' => 0x10000000,
2253
'live_track_auto_start' => 0x20000000,
2254
'live_track_messaging' => 0x40000000,
2255
'instant_input' => 0x80000000, # Device supports instant input feature
2256
},
2257
2258
'weather_report' => +{
2259
'_base_type' => FIT_ENUM,
2260
'current' => 0,
2261
# 'forecast' => 1, # deprecated, use hourly_forecast instead
2262
'hourly_forecast' => 1,
2263
'daily_forecast' => 2,
2264
},
2265
2266
'weather_status' => +{
2267
'_base_type' => FIT_ENUM,
2268
'clear' => 0,
2269
'partly_cloudy' => 1,
2270
'mostly_cloudy' => 2,
2271
'rain' => 3,
2272
'snow' => 4,
2273
'windy' => 5,
2274
'thunderstorms' => 6,
2275
'wintry_mix' => 7,
2276
'fog' => 8,
2277
'hazy' => 11,
2278
'hail' => 12,
2279
'scattered_showers' => 13,
2280
'scattered_thunderstorms' => 14,
2281
'unknown_precipitation' => 15,
2282
'light_rain' => 16,
2283
'heavy_rain' => 17,
2284
'light_snow' => 18,
2285
'heavy_snow' => 19,
2286
'light_rain_snow' => 20,
2287
'heavy_rain_snow' => 21,
2288
'cloudy' => 22,
2289
},
2290
2291
'weather_severity' => +{
2292
'_base_type' => FIT_ENUM,
2293
'unknown' => 0,
2294
'warning' => 1,
2295
'watch' => 2,
2296
'advisory' => 3,
2297
'statement' => 4,
2298
},
2299
2300
'weather_severe_type' => +{
2301
'_base_type' => FIT_ENUM,
2302
'unspecified' => 0,
2303
'tornado' => 1,
2304
'tsunami' => 2,
2305
'hurricane' => 3,
2306
'extreme_wind' => 4,
2307
'typhoon' => 5,
2308
'inland_hurricane' => 6,
2309
'hurricane_force_wind' => 7,
2310
'waterspout' => 8,
2311
'severe_thunderstorm' => 9,
2312
'wreckhouse_winds' => 10,
2313
'les_suetes_wind' => 11,
2314
'avalanche' => 12,
2315
'flash_flood' => 13,
2316
'tropical_storm' => 14,
2317
'inland_tropical_storm' => 15,
2318
'blizzard' => 16,
2319
'ice_storm' => 17,
2320
'freezing_rain' => 18,
2321
'debris_flow' => 19,
2322
'flash_freeze' => 20,
2323
'dust_storm' => 21,
2324
'high_wind' => 22,
2325
'winter_storm' => 23,
2326
'heavy_freezing_spray' => 24,
2327
'extreme_cold' => 25,
2328
'wind_chill' => 26,
2329
'cold_wave' => 27,
2330
'heavy_snow_alert' => 28,
2331
'lake_effect_blowing_snow' => 29,
2332
'snow_squall' => 30,
2333
'lake_effect_snow' => 31,
2334
'winter_weather' => 32,
2335
'sleet' => 33,
2336
'snowfall' => 34,
2337
'snow_and_blowing_snow' => 35,
2338
'blowing_snow' => 36,
2339
'snow_alert' => 37,
2340
'arctic_outflow' => 38,
2341
'freezing_drizzle' => 39,
2342
'storm' => 40,
2343
'storm_surge' => 41,
2344
'rainfall' => 42,
2345
'areal_flood' => 43,
2346
'coastal_flood' => 44,
2347
'lakeshore_flood' => 45,
2348
'excessive_heat' => 46,
2349
'heat' => 47,
2350
'weather' => 48,
2351
'high_heat_and_humidity' => 49,
2352
'humidex_and_health' => 50,
2353
'humidex' => 51,
2354
'gale' => 52,
2355
'freezing_spray' => 53,
2356
'special_marine' => 54,
2357
'squall' => 55,
2358
'strong_wind' => 56,
2359
'lake_wind' => 57,
2360
'marine_weather' => 58,
2361
'wind' => 59,
2362
'small_craft_hazardous_seas' => 60,
2363
'hazardous_seas' => 61,
2364
'small_craft' => 62,
2365
'small_craft_winds' => 63,
2366
'small_craft_rough_bar' => 64,
2367
'high_water_level' => 65,
2368
'ashfall' => 66,
2369
'freezing_fog' => 67,
2370
'dense_fog' => 68,
2371
'dense_smoke' => 69,
2372
'blowing_dust' => 70,
2373
'hard_freeze' => 71,
2374
'freeze' => 72,
2375
'frost' => 73,
2376
'fire_weather' => 74,
2377
'flood' => 75,
2378
'rip_tide' => 76,
2379
'high_surf' => 77,
2380
'smog' => 78,
2381
'air_quality' => 79,
2382
'brisk_wind' => 80,
2383
'air_stagnation' => 81,
2384
'low_water' => 82,
2385
'hydrological' => 83,
2386
'special_weather' => 84,
2387
},
2388
2389
'time_into_day' => +{ # since 00:00:00 UTC
2390
'_base_type' => FIT_UINT32,
2391
},
2392
2393
'localtime_into_day' => +{ # same as above, but in local time zone
2394
'_base_type' => FIT_UINT32,
2395
},
2396
2397
'stroke_type' => +{
2398
'_base_type' => FIT_ENUM,
2399
'no_event' => 0,
2400
'other' => 1,
2401
'serve' => 2,
2402
'forehand' => 3,
2403
'backhand' => 4,
2404
'smash' => 5,
2405
},
2406
2407
'body_location' => +{
2408
'_base_type' => FIT_ENUM,
2409
'left_leg' => 0,
2410
'left_calf' => 1,
2411
'left_shin' => 2,
2412
'left_hamstring' => 3,
2413
'left_quad' => 4,
2414
'left_glute' => 5,
2415
'right_leg' => 6,
2416
'right_calf' => 7,
2417
'right_shin' => 8,
2418
'right_hamstring' => 9,
2419
'right_quad' => 10,
2420
'right_glute' => 11,
2421
'torso_back' => 12,
2422
'left_lower_back' => 13,
2423
'left_upper_back' => 14,
2424
'right_lower_back' => 15,
2425
'right_upper_back' => 16,
2426
'torso_front' => 17,
2427
'left_abdomen' => 18,
2428
'left_chest' => 19,
2429
'right_abdomen' => 20,
2430
'right_chest' => 21,
2431
'left_arm' => 22,
2432
'left_shoulder' => 23,
2433
'left_bicep' => 24,
2434
'left_tricep' => 25,
2435
'left_brachioradialis' => 26,
2436
'left_forearm_extensors' => 27,
2437
'right_arm' => 28,
2438
'right_shoulder' => 29,
2439
'right_bicep' => 30,
2440
'right_tricep' => 31,
2441
'right_brachioradialis' => 32,
2442
'right_forearm_extensors' => 33,
2443
'neck' => 34,
2444
'throat' => 35,
2445
'waist_mid_back' => 36,
2446
'waist_front' => 37,
2447
'waist_left' => 38,
2448
'waist_right' => 39,
2449
},
2450
2451
'segment_lap_status' => +{
2452
'_base_type' => FIT_ENUM,
2453
'end' => 0,
2454
'fail' => 1,
2455
},
2456
2457
'segment_leaderboard_type' => +{
2458
'_base_type' => FIT_ENUM,
2459
'overall' => 0,
2460
'personal_best' => 1,
2461
'connections' => 2,
2462
'group' => 3,
2463
'challenger' => 4,
2464
'kom' => 5,
2465
'qom' => 6,
2466
'pr' => 7,
2467
'goal' => 8,
2468
'carrot' => 9,
2469
'club_leader' => 10,
2470
'rival' => 11,
2471
'last' => 12,
2472
'recent_best' => 13,
2473
'course_record' => 14,
2474
},
2475
2476
'segment_delete_status' => +{
2477
'_base_type' => FIT_ENUM,
2478
'do_not_delete' => 0,
2479
'delete_one' => 1,
2480
'delete_all' => 2,
2481
},
2482
2483
'segment_selection_type' => +{
2484
'_base_type' => FIT_ENUM,
2485
'starred' => 0,
2486
'suggested' => 1,
2487
},
2488
2489
'source_type' => +{
2490
'_base_type' => FIT_ENUM,
2491
'ant' => 0,
2492
'antplus' => 1,
2493
'bluetooth' => 2,
2494
'bluetooth_low_energy' => 3,
2495
'wifi' => 4,
2496
'local' => 5,
2497
},
2498
2499
'local_device_type' => +{
2500
'_base_type' => FIT_UINT8,
2501
'gps' => 0, # Onboard gps receiver
2502
'glonass' => 1, # Onboard glonass receiver
2503
'gps_glonass' => 2, # Onboard gps glonass receiver
2504
'accelerometer' => 3, # Onboard sensor
2505
'barometer' => 4, # Onboard sensor
2506
'temperature' => 5, # Onboard sensor
2507
'whr' => 10, # Onboard wrist HR sensor
2508
'sensor_hub' => 12, # Onboard software package
2509
},
2510
2511
'ble_device_type' => +{
2512
'_base_type' => FIT_ENUM,
2513
'connected_gps' => 0, # GPS that is provided over a proprietary bluetooth service
2514
'heart_rate' => 1,
2515
'bike_power' => 2,
2516
'bike_speed_cadence' => 3,
2517
'bike_speed' => 4,
2518
'bike_cadence' => 5,
2519
'footpod' => 6,
2520
'bike_trainer' => 7, # Indoor-Bike FTMS protocol
2521
},
2522
2523
'ant_channel_id' => +{
2524
'_base_type' => FIT_UINT32Z,
2525
'ant_extended_device_number_upper_nibble' => 0xF0000000,
2526
'ant_transmission_type_lower_nibble' => 0x0F000000,
2527
'ant_device_type' => 0x00FF0000,
2528
'ant_device_number' => 0x0000FFFF,
2529
},
2530
2531
'display_orientation' => +{
2532
'_base_type' => FIT_ENUM,
2533
'auto' => 0,
2534
'portrait' => 1,
2535
'landscape' => 2,
2536
'portrait_flipped' => 3,
2537
'landscape_flipped' => 4,
2538
},
2539
2540
'workout_equipment' => +{
2541
'_base_type' => FIT_ENUM,
2542
'none' => 0,
2543
'swim_fins' => 1,
2544
'swim_kickboard' => 2,
2545
'swim_paddles' => 3,
2546
'swim_pull_buoy' => 4,
2547
'swim_snorkel' => 5,
2548
},
2549
'watchface_mode' => +{
2550
'_base_type' => FIT_ENUM,
2551
'digital' => 0,
2552
'analog' => 1,
2553
'connect_iq' => 2,
2554
'disabled' => 3,
2555
},
2556
2557
'digital_watchface_layout' => +{
2558
'_base_type' => FIT_ENUM,
2559
'traditional' => 0,
2560
'modern' => 1,
2561
'bold' => 2,
2562
},
2563
2564
'analog_watchface_layout' => +{
2565
'_base_type' => FIT_ENUM,
2566
'minimal' => 0,
2567
'traditional' => 1,
2568
'modern' => 2,
2569
},
2570
2571
'rider_position_type' => +{
2572
'_base_type' => FIT_ENUM,
2573
'seated' => 0,
2574
'standing' => 1,
2575
'transition_to_seated' => 2,
2576
'transition_to_standing' => 3,
2577
},
2578
2579
'power_phase_type' => +{
2580
'_base_type' => FIT_ENUM,
2581
'power_phase_start_angle' => 0,
2582
'power_phase_end_angle' => 1,
2583
'power_phase_arc_length' => 2,
2584
'power_phase_center' => 3,
2585
},
2586
2587
'camera_event_type' => +{
2588
'_base_type' => FIT_ENUM,
2589
'video_start' => 0,
2590
'video_split' => 1,
2591
'video_end' => 2,
2592
'photo_taken' => 3,
2593
'video_second_stream_start' => 4,
2594
'video_second_stream_split' => 5,
2595
'video_second_stream_end' => 6,
2596
'video_split_start' => 7,
2597
'video_second_stream_split_start' => 8,
2598
'video_pause' => 11,
2599
'video_second_stream_pause' => 12,
2600
'video_resume' => 13,
2601
'video_second_stream_resume' => 14,
2602
},
2603
2604
'sensor_type' => +{
2605
'_base_type' => FIT_ENUM,
2606
'accelerometer' => 0,
2607
'gyroscope' => 1,
2608
'compass' => 2, # Magnetometer
2609
'barometer' => 3,
2610
},
2611
2612
'bike_light_network_config_type' => +{
2613
'_base_type' => FIT_ENUM,
2614
'auto' => 0,
2615
'individual' => 4,
2616
'high_visibility' => 5,
2617
'trail' => 6,
2618
},
2619
2620
'comm_timeout_type' => +{
2621
'_base_type' => FIT_UINT16,
2622
'wildcard_pairing_timeout' => 0,
2623
'pairing_timeout' => 1,
2624
'connection_lost' => 2,
2625
'connection_timeout' => 3,
2626
},
2627
2628
'camera_orientation_type' => +{
2629
'_base_type' => FIT_ENUM,
2630
'camera_orientation_0' => 0,
2631
'camera_orientation_90' => 1,
2632
'camera_orientation_180' => 2,
2633
'camera_orientation_270' => 3,
2634
},
2635
2636
'attitude_stage' => +{
2637
'_base_type' => FIT_ENUM,
2638
'failed' => 0,
2639
'aligning' => 1,
2640
'degraded' => 2,
2641
'valid' => 3,
2642
},
2643
2644
'attitude_validity' => +{
2645
'_base_type' => FIT_UINT16,
2646
'track_angle_heading_valid' => 0x0001,
2647
'pitch_valid' => 0x0002,
2648
'roll_valid' => 0x0004,
2649
'lateral_body_accel_valid' => 0x0008,
2650
'normal_body_accel_valid' => 0x0010,
2651
'turn_rate_valid' => 0x0020,
2652
'hw_fail' => 0x0040,
2653
'mag_invalid' => 0x0080,
2654
'no_gps' => 0x0100,
2655
'gps_invalid' => 0x0200,
2656
'solution_coasting' => 0x0400,
2657
'true_track_angle' => 0x0800,
2658
'magnetic_heading' => 0x1000,
2659
},
2660
2661
'auto_sync_frequency' => +{
2662
'_base_type' => FIT_ENUM,
2663
'never' => 0,
2664
'occasionally' => 1,
2665
'frequent' => 2,
2666
'once_a_day' => 3,
2667
'remote' => 4,
2668
},
2669
2670
'exd_layout' => +{
2671
'_base_type' => FIT_ENUM,
2672
'full_screen' => 0,
2673
'half_vertical' => 1,
2674
'half_horizontal' => 2,
2675
'half_vertical_right_split' => 3,
2676
'half_horizontal_bottom_split' => 4,
2677
'full_quarter_split' => 5,
2678
'half_vertical_left_split' => 6,
2679
'half_horizontal_top_split' => 7,
2680
'dynamic' => 8, # The EXD may display the configured concepts in any layout it sees fit.
2681
},
2682
2683
'exd_display_type' => +{
2684
'_base_type' => FIT_ENUM,
2685
'numerical' => 0,
2686
'simple' => 1,
2687
'graph' => 2,
2688
'bar' => 3,
2689
'circle_graph' => 4,
2690
'virtual_partner' => 5,
2691
'balance' => 6,
2692
'string_list' => 7,
2693
'string' => 8,
2694
'simple_dynamic_icon' => 9,
2695
'gauge' => 10,
2696
},
2697
2698
'exd_data_units' => +{
2699
'_base_type' => FIT_ENUM,
2700
'no_units' => 0,
2701
'laps' => 1,
2702
'miles_per_hour' => 2,
2703
'kilometers_per_hour' => 3,
2704
'feet_per_hour' => 4,
2705
'meters_per_hour' => 5,
2706
'degrees_celsius' => 6,
2707
'degrees_farenheit' => 7,
2708
'zone' => 8,
2709
'gear' => 9,
2710
'rpm' => 10,
2711
'bpm' => 11,
2712
'degrees' => 12,
2713
'millimeters' => 13,
2714
'meters' => 14,
2715
'kilometers' => 15,
2716
'feet' => 16,
2717
'yards' => 17,
2718
'kilofeet' => 18,
2719
'miles' => 19,
2720
'time' => 20,
2721
'enum_turn_type' => 21,
2722
'percent' => 22,
2723
'watts' => 23,
2724
'watts_per_kilogram' => 24,
2725
'enum_battery_status' => 25,
2726
'enum_bike_light_beam_angle_mode' => 26,
2727
'enum_bike_light_battery_status' => 27,
2728
'enum_bike_light_network_config_type' => 28,
2729
'lights' => 29,
2730
'seconds' => 30,
2731
'minutes' => 31,
2732
'hours' => 32,
2733
'calories' => 33,
2734
'kilojoules' => 34,
2735
'milliseconds' => 35,
2736
'second_per_mile' => 36,
2737
'second_per_kilometer' => 37,
2738
'centimeter' => 38,
2739
'enum_course_point' => 39,
2740
'bradians' => 40,
2741
'enum_sport' => 41,
2742
'inches_hg' => 42,
2743
'mm_hg' => 43,
2744
'mbars' => 44,
2745
'hecto_pascals' => 45,
2746
'feet_per_min' => 46,
2747
'meters_per_min' => 47,
2748
'meters_per_sec' => 48,
2749
'eight_cardinal' => 49,
2750
},
2751
2752
'exd_qualifiers' => +{
2753
'_base_type' => FIT_ENUM,
2754
'no_qualifier' => 0,
2755
'instantaneous' => 1,
2756
'average' => 2,
2757
'lap' => 3,
2758
'maximum' => 4,
2759
'maximum_average' => 5,
2760
'maximum_lap' => 6,
2761
'last_lap' => 7,
2762
'average_lap' => 8,
2763
'to_destination' => 9,
2764
'to_go' => 10,
2765
'to_next' => 11,
2766
'next_course_point' => 12,
2767
'total' => 13,
2768
'three_second_average' => 14,
2769
'ten_second_average' => 15,
2770
'thirty_second_average' => 16,
2771
'percent_maximum' => 17,
2772
'percent_maximum_average' => 18,
2773
'lap_percent_maximum' => 19,
2774
'elapsed' => 20,
2775
'sunrise' => 21,
2776
'sunset' => 22,
2777
'compared_to_virtual_partner' => 23,
2778
'maximum_24h' => 24,
2779
'minimum_24h' => 25,
2780
'minimum' => 26,
2781
'first' => 27,
2782
'second' => 28,
2783
'third' => 29,
2784
'shifter' => 30,
2785
'last_sport' => 31,
2786
'moving' => 32,
2787
'stopped' => 33,
2788
'estimated_total' => 34,
2789
'zone_9' => 242,
2790
'zone_8' => 243,
2791
'zone_7' => 244,
2792
'zone_6' => 245,
2793
'zone_5' => 246,
2794
'zone_4' => 247,
2795
'zone_3' => 248,
2796
'zone_2' => 249,
2797
'zone_1' => 250,
2798
},
2799
2800
'exd_descriptors' => +{
2801
'_base_type' => FIT_ENUM,
2802
'bike_light_battery_status' => 0,
2803
'beam_angle_status' => 1,
2804
'batery_level' => 2,
2805
'light_network_mode' => 3,
2806
'number_lights_connected' => 4,
2807
'cadence' => 5,
2808
'distance' => 6,
2809
'estimated_time_of_arrival' => 7,
2810
'heading' => 8,
2811
'time' => 9,
2812
'battery_level' => 10,
2813
'trainer_resistance' => 11,
2814
'trainer_target_power' => 12,
2815
'time_seated' => 13,
2816
'time_standing' => 14,
2817
'elevation' => 15,
2818
'grade' => 16,
2819
'ascent' => 17,
2820
'descent' => 18,
2821
'vertical_speed' => 19,
2822
'di2_battery_level' => 20,
2823
'front_gear' => 21,
2824
'rear_gear' => 22,
2825
'gear_ratio' => 23,
2826
'heart_rate' => 24,
2827
'heart_rate_zone' => 25,
2828
'time_in_heart_rate_zone' => 26,
2829
'heart_rate_reserve' => 27,
2830
'calories' => 28,
2831
'gps_accuracy' => 29,
2832
'gps_signal_strength' => 30,
2833
'temperature' => 31,
2834
'time_of_day' => 32,
2835
'balance' => 33,
2836
'pedal_smoothness' => 34,
2837
'power' => 35,
2838
'functional_threshold_power' => 36,
2839
'intensity_factor' => 37,
2840
'work' => 38,
2841
'power_ratio' => 39,
2842
'normalized_power' => 40,
2843
'training_stress_score' => 41,
2844
'time_on_zone' => 42,
2845
'speed' => 43,
2846
'laps' => 44,
2847
'reps' => 45,
2848
'workout_step' => 46,
2849
'course_distance' => 47,
2850
'navigation_distance' => 48,
2851
'course_estimated_time_of_arrival' => 49,
2852
'navigation_estimated_time_of_arrival' => 50,
2853
'course_time' => 51,
2854
'navigation_time' => 52,
2855
'course_heading' => 53,
2856
'navigation_heading' => 54,
2857
'power_zone' => 55,
2858
'torque_effectiveness' => 56,
2859
'timer_time' => 57,
2860
'power_weight_ratio' => 58,
2861
'left_platform_center_offset' => 59,
2862
'right_platform_center_offset' => 60,
2863
'left_power_phase_start_angle' => 61,
2864
'right_power_phase_start_angle' => 62,
2865
'left_power_phase_finish_angle' => 63,
2866
'right_power_phase_finish_angle' => 64,
2867
'gears' => 65,
2868
'pace' => 66,
2869
'training_effect' => 67,
2870
'vertical_oscillation' => 68,
2871
'vertical_ratio' => 69,
2872
'ground_contact_time' => 70,
2873
'left_ground_contact_time_balance' => 71,
2874
'right_ground_contact_time_balance' => 72,
2875
'stride_length' => 73,
2876
'running_cadence' => 74,
2877
'performance_condition' => 75,
2878
'course_type' => 76,
2879
'time_in_power_zone' => 77,
2880
'navigation_turn' => 78,
2881
'course_location' => 79,
2882
'navigation_location' => 80,
2883
'compass' => 81,
2884
'gear_combo' => 82,
2885
'muscle_oxygen' => 83,
2886
'icon' => 84,
2887
'compass_heading' => 85,
2888
'gps_heading' => 86,
2889
'gps_elevation' => 87,
2890
'anaerobic_training_effect' => 88,
2891
'course' => 89,
2892
'off_course' => 90,
2893
'glide_ratio' => 91,
2894
'vertical_distance' => 92,
2895
'vmg' => 93,
2896
'ambient_pressure' => 94,
2897
'pressure' => 95,
2898
'vam' => 96,
2899
},
2900
2901
'auto_activity_detect' => +{
2902
'_base_type' => FIT_UINT32,
2903
'none' => 0x00000000,
2904
'running' => 0x00000001,
2905
'cycling' => 0x00000002,
2906
'swimming' => 0x00000004,
2907
'walking' => 0x00000008,
2908
'elliptical' => 0x00000020,
2909
'sedentary' => 0x00000400,
2910
},
2911
2912
'supported_exd_screen_layouts' => +{
2913
'_base_type' => FIT_UINT32Z,
2914
'full_screen' => 0x00000001,
2915
'half_vertical' => 0x00000002,
2916
'half_horizontal' => 0x00000004,
2917
'half_vertical_right_split' => 0x00000008,
2918
'half_horizontal_bottom_split' => 0x00000010,
2919
'full_quarter_split' => 0x00000020,
2920
'half_vertical_left_split' => 0x00000040,
2921
'half_horizontal_top_split' => 0x00000080,
2922
},
2923
2924
'fit_base_type' => +{
2925
'_base_type' => FIT_UINT8,
2926
'enum' => 0,
2927
'sint8' => 1,
2928
'uint8' => 2,
2929
'sint16' => 131,
2930
'uint16' => 132,
2931
'sint32' => 133,
2932
'uint32' => 134,
2933
'string' => 7,
2934
'float32' => 136,
2935
'float64' => 137,
2936
'uint8z' => 10,
2937
'uint16z' => 139,
2938
'uint32z' => 140,
2939
'byte' => 13,
2940
'sint64' => 142,
2941
'uint64' => 143,
2942
'uint64z' => 144,
2943
},
2944
2945
'turn_type' => +{
2946
'_base_type' => FIT_ENUM,
2947
'arriving_idx' => 0,
2948
'arriving_left_idx' => 1,
2949
'arriving_right_idx' => 2,
2950
'arriving_via_idx' => 3,
2951
'arriving_via_left_idx' => 4,
2952
'arriving_via_right_idx' => 5,
2953
'bear_keep_left_idx' => 6,
2954
'bear_keep_right_idx' => 7,
2955
'continue_idx' => 8,
2956
'exit_left_idx' => 9,
2957
'exit_right_idx' => 10,
2958
'ferry_idx' => 11,
2959
'roundabout_45_idx' => 12,
2960
'roundabout_90_idx' => 13,
2961
'roundabout_135_idx' => 14,
2962
'roundabout_180_idx' => 15,
2963
'roundabout_225_idx' => 16,
2964
'roundabout_270_idx' => 17,
2965
'roundabout_315_idx' => 18,
2966
'roundabout_360_idx' => 19,
2967
'roundabout_neg_45_idx' => 20,
2968
'roundabout_neg_90_idx' => 21,
2969
'roundabout_neg_135_idx' => 22,
2970
'roundabout_neg_180_idx' => 23,
2971
'roundabout_neg_225_idx' => 24,
2972
'roundabout_neg_270_idx' => 25,
2973
'roundabout_neg_315_idx' => 26,
2974
'roundabout_neg_360_idx' => 27,
2975
'roundabout_generic_idx' => 28,
2976
'roundabout_neg_generic_idx' => 29,
2977
'sharp_turn_left_idx' => 30,
2978
'sharp_turn_right_idx' => 31,
2979
'turn_left_idx' => 32,
2980
'turn_right_idx' => 33,
2981
'uturn_left_idx' => 34,
2982
'uturn_right_idx' => 35,
2983
'icon_inv_idx' => 36,
2984
'icon_idx_cnt' => 37,
2985
},
2986
2987
'bike_light_beam_angle_mode' => +{
2988
'_base_type' => FIT_ENUM,
2989
'manual' => 0,
2990
'auto' => 1,
2991
},
2992
2993
'fit_base_unit' => +{
2994
'_base_type' => FIT_UINT16,
2995
'other' => 0,
2996
'kilogram' => 1,
2997
'pound' => 2,
2998
},
2999
3000
'set_type' => +{
3001
'_base_type' => FIT_UINT8,
3002
'rest' => 0,
3003
'active' => 1,
3004
},
3005
3006
'max_met_category' => +{
3007
'_base_type' => FIT_ENUM,
3008
'generic' => 0,
3009
'cycling' => 1,
3010
},
3011
3012
'exercise_category' => +{
3013
'_base_type' => FIT_UINT16,
3014
'bench_press' => 0,
3015
'calf_raise' => 1,
3016
'cardio' => 2,
3017
'carry' => 3,
3018
'chop' => 4,
3019
'core' => 5,
3020
'crunch' => 6,
3021
'curl' => 7,
3022
'deadlift' => 8,
3023
'flye' => 9,
3024
'hip_raise' => 10,
3025
'hip_stability' => 11,
3026
'hip_swing' => 12,
3027
'hyperextension' => 13,
3028
'lateral_raise' => 14,
3029
'leg_curl' => 15,
3030
'leg_raise' => 16,
3031
'lunge' => 17,
3032
'olympic_lift' => 18,
3033
'plank' => 19,
3034
'plyo' => 20,
3035
'pull_up' => 21,
3036
'push_up' => 22,
3037
'row' => 23,
3038
'shoulder_press' => 24,
3039
'shoulder_stability' => 25,
3040
'shrug' => 26,
3041
'sit_up' => 27,
3042
'squat' => 28,
3043
'total_body' => 29,
3044
'triceps_extension' => 30,
3045
'warm_up' => 31,
3046
'run' => 32,
3047
'unknown' => 65534,
3048
},
3049
3050
'bench_press_exercise_name' => +{
3051
'_base_type' => FIT_UINT16,
3052
'alternating_dumbbell_chest_press_on_swiss_ball' => 0,
3053
'barbell_bench_press' => 1,
3054
'barbell_board_bench_press' => 2,
3055
'barbell_floor_press' => 3,
3056
'close_grip_barbell_bench_press' => 4,
3057
'decline_dumbbell_bench_press' => 5,
3058
'dumbbell_bench_press' => 6,
3059
'dumbbell_floor_press' => 7,
3060
'incline_barbell_bench_press' => 8,
3061
'incline_dumbbell_bench_press' => 9,
3062
'incline_smith_machine_bench_press' => 10,
3063
'isometric_barbell_bench_press' => 11,
3064
'kettlebell_chest_press' => 12,
3065
'neutral_grip_dumbbell_bench_press' => 13,
3066
'neutral_grip_dumbbell_incline_bench_press' => 14,
3067
'one_arm_floor_press' => 15,
3068
'weighted_one_arm_floor_press' => 16,
3069
'partial_lockout' => 17,
3070
'reverse_grip_barbell_bench_press' => 18,
3071
'reverse_grip_incline_bench_press' => 19,
3072
'single_arm_cable_chest_press' => 20,
3073
'single_arm_dumbbell_bench_press' => 21,
3074
'smith_machine_bench_press' => 22,
3075
'swiss_ball_dumbbell_chest_press' => 23,
3076
'triple_stop_barbell_bench_press' => 24,
3077
'wide_grip_barbell_bench_press' => 25,
3078
'alternating_dumbbell_chest_press' => 26,
3079
},
3080
3081
'calf_raise_exercise_name' => +{
3082
'_base_type' => FIT_UINT16,
3083
'3_way_calf_raise' => 0,
3084
'3_way_weighted_calf_raise' => 1,
3085
'3_way_single_leg_calf_raise' => 2,
3086
'3_way_weighted_single_leg_calf_raise' => 3,
3087
'donkey_calf_raise' => 4,
3088
'weighted_donkey_calf_raise' => 5,
3089
'seated_calf_raise' => 6,
3090
'weighted_seated_calf_raise' => 7,
3091
'seated_dumbbell_toe_raise' => 8,
3092
'single_leg_bent_knee_calf_raise' => 9,
3093
'weighted_single_leg_bent_knee_calf_raise' => 10,
3094
'single_leg_decline_push_up' => 11,
3095
'single_leg_donkey_calf_raise' => 12,
3096
'weighted_single_leg_donkey_calf_raise' => 13,
3097
'single_leg_hip_raise_with_knee_hold' => 14,
3098
'single_leg_standing_calf_raise' => 15,
3099
'single_leg_standing_dumbbell_calf_raise' => 16,
3100
'standing_barbell_calf_raise' => 17,
3101
'standing_calf_raise' => 18,
3102
'weighted_standing_calf_raise' => 19,
3103
'standing_dumbbell_calf_raise' => 20,
3104
},
3105
3106
'cardio_exercise_name' => +{
3107
'_base_type' => FIT_UINT16,
3108
'bob_and_weave_circle' => 0,
3109
'weighted_bob_and_weave_circle' => 1,
3110
'cardio_core_crawl' => 2,
3111
'weighted_cardio_core_crawl' => 3,
3112
'double_under' => 4,
3113
'weighted_double_under' => 5,
3114
'jump_rope' => 6,
3115
'weighted_jump_rope' => 7,
3116
'jump_rope_crossover' => 8,
3117
'weighted_jump_rope_crossover' => 9,
3118
'jump_rope_jog' => 10,
3119
'weighted_jump_rope_jog' => 11,
3120
'jumping_jacks' => 12,
3121
'weighted_jumping_jacks' => 13,
3122
'ski_moguls' => 14,
3123
'weighted_ski_moguls' => 15,
3124
'split_jacks' => 16,
3125
'weighted_split_jacks' => 17,
3126
'squat_jacks' => 18,
3127
'weighted_squat_jacks' => 19,
3128
'triple_under' => 20,
3129
'weighted_triple_under' => 21,
3130
},
3131
3132
'carry_exercise_name' => +{
3133
'_base_type' => FIT_UINT16,
3134
'bar_holds' => 0,
3135
'farmers_walk' => 1,
3136
'farmers_walk_on_toes' => 2,
3137
'hex_dumbbell_hold' => 3,
3138
'overhead_carry' => 4,
3139
},
3140
3141
'chop_exercise_name' => +{
3142
'_base_type' => FIT_UINT16,
3143
'cable_pull_through' => 0,
3144
'cable_rotational_lift' => 1,
3145
'cable_woodchop' => 2,
3146
'cross_chop_to_knee' => 3,
3147
'weighted_cross_chop_to_knee' => 4,
3148
'dumbbell_chop' => 5,
3149
'half_kneeling_rotation' => 6,
3150
'weighted_half_kneeling_rotation' => 7,
3151
'half_kneeling_rotational_chop' => 8,
3152
'half_kneeling_rotational_reverse_chop' => 9,
3153
'half_kneeling_stability_chop' => 10,
3154
'half_kneeling_stability_reverse_chop' => 11,
3155
'kneeling_rotational_chop' => 12,
3156
'kneeling_rotational_reverse_chop' => 13,
3157
'kneeling_stability_chop' => 14,
3158
'kneeling_woodchopper' => 15,
3159
'medicine_ball_wood_chops' => 16,
3160
'power_squat_chops' => 17,
3161
'weighted_power_squat_chops' => 18,
3162
'standing_rotational_chop' => 19,
3163
'standing_split_rotational_chop' => 20,
3164
'standing_split_rotational_reverse_chop' => 21,
3165
'standing_stability_reverse_chop' => 22,
3166
},
3167
3168
'core_exercise_name' => +{
3169
'_base_type' => FIT_UINT16,
3170
'abs_jabs' => 0,
3171
'weighted_abs_jabs' => 1,
3172
'alternating_plate_reach' => 2,
3173
'barbell_rollout' => 3,
3174
'weighted_barbell_rollout' => 4,
3175
'body_bar_oblique_twist' => 5,
3176
'cable_core_press' => 6,
3177
'cable_side_bend' => 7,
3178
'side_bend' => 8,
3179
'weighted_side_bend' => 9,
3180
'crescent_circle' => 10,
3181
'weighted_crescent_circle' => 11,
3182
'cycling_russian_twist' => 12,
3183
'weighted_cycling_russian_twist' => 13,
3184
'elevated_feet_russian_twist' => 14,
3185
'weighted_elevated_feet_russian_twist' => 15,
3186
'half_turkish_get_up' => 16,
3187
'kettlebell_windmill' => 17,
3188
'kneeling_ab_wheel' => 18,
3189
'weighted_kneeling_ab_wheel' => 19,
3190
'modified_front_lever' => 20,
3191
'open_knee_tucks' => 21,
3192
'weighted_open_knee_tucks' => 22,
3193
'side_abs_leg_lift' => 23,
3194
'weighted_side_abs_leg_lift' => 24,
3195
'swiss_ball_jackknife' => 25,
3196
'weighted_swiss_ball_jackknife' => 26,
3197
'swiss_ball_pike' => 27,
3198
'weighted_swiss_ball_pike' => 28,
3199
'swiss_ball_rollout' => 29,
3200
'weighted_swiss_ball_rollout' => 30,
3201
'triangle_hip_press' => 31,
3202
'weighted_triangle_hip_press' => 32,
3203
'trx_suspended_jackknife' => 33,
3204
'weighted_trx_suspended_jackknife' => 34,
3205
'u_boat' => 35,
3206
'weighted_u_boat' => 36,
3207
'windmill_switches' => 37,
3208
'weighted_windmill_switches' => 38,
3209
'alternating_slide_out' => 39,
3210
'weighted_alternating_slide_out' => 40,
3211
'ghd_back_extensions' => 41,
3212
'weighted_ghd_back_extensions' => 42,
3213
'overhead_walk' => 43,
3214
'inchworm' => 44,
3215
'weighted_modified_front_lever' => 45,
3216
'russian_twist' => 46,
3217
'abdominal_leg_rotations' => 47, # Deprecated do not use
3218
'arm_and_leg_extension_on_knees' => 48,
3219
'bicycle' => 49,
3220
'bicep_curl_with_leg_extension' => 50,
3221
'cat_cow' => 51,
3222
'corkscrew' => 52,
3223
'criss_cross' => 53,
3224
'criss_cross_with_ball' => 54, # Deprecated do not use
3225
'double_leg_stretch' => 55,
3226
'knee_folds' => 56,
3227
'lower_lift' => 57,
3228
'neck_pull' => 58,
3229
'pelvic_clocks' => 59,
3230
'roll_over' => 60,
3231
'roll_up' => 61,
3232
'rolling' => 62,
3233
'rowing_1' => 63,
3234
'rowing_2' => 64,
3235
'scissors' => 65,
3236
'single_leg_circles' => 66,
3237
'single_leg_stretch' => 67,
3238
'snake_twist_1_and_2' => 68, # Deprecated do not use
3239
'swan' => 69,
3240
'swimming' => 70,
3241
'teaser' => 71,
3242
'the_hundred' => 72,
3243
},
3244
3245
'crunch_exercise_name' => +{
3246
'_base_type' => FIT_UINT16,
3247
'bicycle_crunch' => 0,
3248
'cable_crunch' => 1,
3249
'circular_arm_crunch' => 2,
3250
'crossed_arms_crunch' => 3,
3251
'weighted_crossed_arms_crunch' => 4,
3252
'cross_leg_reverse_crunch' => 5,
3253
'weighted_cross_leg_reverse_crunch' => 6,
3254
'crunch_chop' => 7,
3255
'weighted_crunch_chop' => 8,
3256
'double_crunch' => 9,
3257
'weighted_double_crunch' => 10,
3258
'elbow_to_knee_crunch' => 11,
3259
'weighted_elbow_to_knee_crunch' => 12,
3260
'flutter_kicks' => 13,
3261
'weighted_flutter_kicks' => 14,
3262
'foam_roller_reverse_crunch_on_bench' => 15,
3263
'weighted_foam_roller_reverse_crunch_on_bench' => 16,
3264
'foam_roller_reverse_crunch_with_dumbbell' => 17,
3265
'foam_roller_reverse_crunch_with_medicine_ball' => 18,
3266
'frog_press' => 19,
3267
'hanging_knee_raise_oblique_crunch' => 20,
3268
'weighted_hanging_knee_raise_oblique_crunch' => 21,
3269
'hip_crossover' => 22,
3270
'weighted_hip_crossover' => 23,
3271
'hollow_rock' => 24,
3272
'weighted_hollow_rock' => 25,
3273
'incline_reverse_crunch' => 26,
3274
'weighted_incline_reverse_crunch' => 27,
3275
'kneeling_cable_crunch' => 28,
3276
'kneeling_cross_crunch' => 29,
3277
'weighted_kneeling_cross_crunch' => 30,
3278
'kneeling_oblique_cable_crunch' => 31,
3279
'knees_to_elbow' => 32,
3280
'leg_extensions' => 33,
3281
'weighted_leg_extensions' => 34,
3282
'leg_levers' => 35,
3283
'mcgill_curl_up' => 36,
3284
'weighted_mcgill_curl_up' => 37,
3285
'modified_pilates_roll_up_with_ball' => 38,
3286
'weighted_modified_pilates_roll_up_with_ball' => 39,
3287
'pilates_crunch' => 40,
3288
'weighted_pilates_crunch' => 41,
3289
'pilates_roll_up_with_ball' => 42,
3290
'weighted_pilates_roll_up_with_ball' => 43,
3291
'raised_legs_crunch' => 44,
3292
'weighted_raised_legs_crunch' => 45,
3293
'reverse_crunch' => 46,
3294
'weighted_reverse_crunch' => 47,
3295
'reverse_crunch_on_a_bench' => 48,
3296
'weighted_reverse_crunch_on_a_bench' => 49,
3297
'reverse_curl_and_lift' => 50,
3298
'weighted_reverse_curl_and_lift' => 51,
3299
'rotational_lift' => 52,
3300
'weighted_rotational_lift' => 53,
3301
'seated_alternating_reverse_crunch' => 54,
3302
'weighted_seated_alternating_reverse_crunch' => 55,
3303
'seated_leg_u' => 56,
3304
'weighted_seated_leg_u' => 57,
3305
'side_to_side_crunch_and_weave' => 58,
3306
'weighted_side_to_side_crunch_and_weave' => 59,
3307
'single_leg_reverse_crunch' => 60,
3308
'weighted_single_leg_reverse_crunch' => 61,
3309
'skater_crunch_cross' => 62,
3310
'weighted_skater_crunch_cross' => 63,
3311
'standing_cable_crunch' => 64,
3312
'standing_side_crunch' => 65,
3313
'step_climb' => 66,
3314
'weighted_step_climb' => 67,
3315
'swiss_ball_crunch' => 68,
3316
'swiss_ball_reverse_crunch' => 69,
3317
'weighted_swiss_ball_reverse_crunch' => 70,
3318
'swiss_ball_russian_twist' => 71,
3319
'weighted_swiss_ball_russian_twist' => 72,
3320
'swiss_ball_side_crunch' => 73,
3321
'weighted_swiss_ball_side_crunch' => 74,
3322
'thoracic_crunches_on_foam_roller' => 75,
3323
'weighted_thoracic_crunches_on_foam_roller' => 76,
3324
'triceps_crunch' => 77,
3325
'weighted_bicycle_crunch' => 78,
3326
'weighted_crunch' => 79,
3327
'weighted_swiss_ball_crunch' => 80,
3328
'toes_to_bar' => 81,
3329
'weighted_toes_to_bar' => 82,
3330
'crunch' => 83,
3331
'straight_leg_crunch_with_ball' => 84,
3332
},
3333
3334
'curl_exercise_name' => +{
3335
'_base_type' => FIT_UINT16,
3336
'alternating_dumbbell_biceps_curl' => 0,
3337
'alternating_dumbbell_biceps_curl_on_swiss_ball' => 1,
3338
'alternating_incline_dumbbell_biceps_curl' => 2,
3339
'barbell_biceps_curl' => 3,
3340
'barbell_reverse_wrist_curl' => 4,
3341
'barbell_wrist_curl' => 5,
3342
'behind_the_back_barbell_reverse_wrist_curl' => 6,
3343
'behind_the_back_one_arm_cable_curl' => 7,
3344
'cable_biceps_curl' => 8,
3345
'cable_hammer_curl' => 9,
3346
'cheating_barbell_biceps_curl' => 10,
3347
'close_grip_ez_bar_biceps_curl' => 11,
3348
'cross_body_dumbbell_hammer_curl' => 12,
3349
'dead_hang_biceps_curl' => 13,
3350
'decline_hammer_curl' => 14,
3351
'dumbbell_biceps_curl_with_static_hold' => 15,
3352
'dumbbell_hammer_curl' => 16,
3353
'dumbbell_reverse_wrist_curl' => 17,
3354
'dumbbell_wrist_curl' => 18,
3355
'ez_bar_preacher_curl' => 19,
3356
'forward_bend_biceps_curl' => 20,
3357
'hammer_curl_to_press' => 21,
3358
'incline_dumbbell_biceps_curl' => 22,
3359
'incline_offset_thumb_dumbbell_curl' => 23,
3360
'kettlebell_biceps_curl' => 24,
3361
'lying_concentration_cable_curl' => 25,
3362
'one_arm_preacher_curl' => 26,
3363
'plate_pinch_curl' => 27,
3364
'preacher_curl_with_cable' => 28,
3365
'reverse_ez_bar_curl' => 29,
3366
'reverse_grip_wrist_curl' => 30,
3367
'reverse_grip_barbell_biceps_curl' => 31,
3368
'seated_alternating_dumbbell_biceps_curl' => 32,
3369
'seated_dumbbell_biceps_curl' => 33,
3370
'seated_reverse_dumbbell_curl' => 34,
3371
'split_stance_offset_pinky_dumbbell_curl' => 35,
3372
'standing_alternating_dumbbell_curls' => 36,
3373
'standing_dumbbell_biceps_curl' => 37,
3374
'standing_ez_bar_biceps_curl' => 38,
3375
'static_curl' => 39,
3376
'swiss_ball_dumbbell_overhead_triceps_extension' => 40,
3377
'swiss_ball_ez_bar_preacher_curl' => 41,
3378
'twisting_standing_dumbbell_biceps_curl' => 42,
3379
'wide_grip_ez_bar_biceps_curl' => 43,
3380
},
3381
3382
'deadlift_exercise_name' => +{
3383
'_base_type' => FIT_UINT16,
3384
'barbell_deadlift' => 0,
3385
'barbell_straight_leg_deadlift' => 1,
3386
'dumbbell_deadlift' => 2,
3387
'dumbbell_single_leg_deadlift_to_row' => 3,
3388
'dumbbell_straight_leg_deadlift' => 4,
3389
'kettlebell_floor_to_shelf' => 5,
3390
'one_arm_one_leg_deadlift' => 6,
3391
'rack_pull' => 7,
3392
'rotational_dumbbell_straight_leg_deadlift' => 8,
3393
'single_arm_deadlift' => 9,
3394
'single_leg_barbell_deadlift' => 10,
3395
'single_leg_barbell_straight_leg_deadlift' => 11,
3396
'single_leg_deadlift_with_barbell' => 12,
3397
'single_leg_rdl_circuit' => 13,
3398
'single_leg_romanian_deadlift_with_dumbbell' => 14,
3399
'sumo_deadlift' => 15,
3400
'sumo_deadlift_high_pull' => 16,
3401
'trap_bar_deadlift' => 17,
3402
'wide_grip_barbell_deadlift' => 18,
3403
},
3404
3405
'flye_exercise_name' => +{
3406
'_base_type' => FIT_UINT16,
3407
'cable_crossover' => 0,
3408
'decline_dumbbell_flye' => 1,
3409
'dumbbell_flye' => 2,
3410
'incline_dumbbell_flye' => 3,
3411
'kettlebell_flye' => 4,
3412
'kneeling_rear_flye' => 5,
3413
'single_arm_standing_cable_reverse_flye' => 6,
3414
'swiss_ball_dumbbell_flye' => 7,
3415
'arm_rotations' => 8,
3416
'hug_a_tree' => 9,
3417
},
3418
3419
'hip_raise_exercise_name' => +{
3420
'_base_type' => FIT_UINT16,
3421
'barbell_hip_thrust_on_floor' => 0,
3422
'barbell_hip_thrust_with_bench' => 1,
3423
'bent_knee_swiss_ball_reverse_hip_raise' => 2,
3424
'weighted_bent_knee_swiss_ball_reverse_hip_raise' => 3,
3425
'bridge_with_leg_extension' => 4,
3426
'weighted_bridge_with_leg_extension' => 5,
3427
'clam_bridge' => 6,
3428
'front_kick_tabletop' => 7,
3429
'weighted_front_kick_tabletop' => 8,
3430
'hip_extension_and_cross' => 9,
3431
'weighted_hip_extension_and_cross' => 10,
3432
'hip_raise' => 11,
3433
'weighted_hip_raise' => 12,
3434
'hip_raise_with_feet_on_swiss_ball' => 13,
3435
'weighted_hip_raise_with_feet_on_swiss_ball' => 14,
3436
'hip_raise_with_head_on_bosu_ball' => 15,
3437
'weighted_hip_raise_with_head_on_bosu_ball' => 16,
3438
'hip_raise_with_head_on_swiss_ball' => 17,
3439
'weighted_hip_raise_with_head_on_swiss_ball' => 18,
3440
'hip_raise_with_knee_squeeze' => 19,
3441
'weighted_hip_raise_with_knee_squeeze' => 20,
3442
'incline_rear_leg_extension' => 21,
3443
'weighted_incline_rear_leg_extension' => 22,
3444
'kettlebell_swing' => 23,
3445
'marching_hip_raise' => 24,
3446
'weighted_marching_hip_raise' => 25,
3447
'marching_hip_raise_with_feet_on_a_swiss_ball' => 26,
3448
'weighted_marching_hip_raise_with_feet_on_a_swiss_ball' => 27,
3449
'reverse_hip_raise' => 28,
3450
'weighted_reverse_hip_raise' => 29,
3451
'single_leg_hip_raise' => 30,
3452
'weighted_single_leg_hip_raise' => 31,
3453
'single_leg_hip_raise_with_foot_on_bench' => 32,
3454
'weighted_single_leg_hip_raise_with_foot_on_bench' => 33,
3455
'single_leg_hip_raise_with_foot_on_bosu_ball' => 34,
3456
'weighted_single_leg_hip_raise_with_foot_on_bosu_ball' => 35,
3457
'single_leg_hip_raise_with_foot_on_foam_roller' => 36,
3458
'weighted_single_leg_hip_raise_with_foot_on_foam_roller' => 37,
3459
'single_leg_hip_raise_with_foot_on_medicine_ball' => 38,
3460
'weighted_single_leg_hip_raise_with_foot_on_medicine_ball' => 39,
3461
'single_leg_hip_raise_with_head_on_bosu_ball' => 40,
3462
'weighted_single_leg_hip_raise_with_head_on_bosu_ball' => 41,
3463
'weighted_clam_bridge' => 42,
3464
'single_leg_swiss_ball_hip_raise_and_leg_curl' => 43,
3465
'clams' => 44,
3466
'inner_thigh_circles' => 45, # Deprecated do not use
3467
'inner_thigh_side_lift' => 46, # Deprecated do not use
3468
'leg_circles' => 47,
3469
'leg_lift' => 48,
3470
'leg_lift_in_external_rotation' => 49,
3471
},
3472
3473
'hip_stability_exercise_name' => +{
3474
'_base_type' => FIT_UINT16,
3475
'band_side_lying_leg_raise' => 0,
3476
'dead_bug' => 1,
3477
'weighted_dead_bug' => 2,
3478
'external_hip_raise' => 3,
3479
'weighted_external_hip_raise' => 4,
3480
'fire_hydrant_kicks' => 5,
3481
'weighted_fire_hydrant_kicks' => 6,
3482
'hip_circles' => 7,
3483
'weighted_hip_circles' => 8,
3484
'inner_thigh_lift' => 9,
3485
'weighted_inner_thigh_lift' => 10,
3486
'lateral_walks_with_band_at_ankles' => 11,
3487
'pretzel_side_kick' => 12,
3488
'weighted_pretzel_side_kick' => 13,
3489
'prone_hip_internal_rotation' => 14,
3490
'weighted_prone_hip_internal_rotation' => 15,
3491
'quadruped' => 16,
3492
'quadruped_hip_extension' => 17,
3493
'weighted_quadruped_hip_extension' => 18,
3494
'quadruped_with_leg_lift' => 19,
3495
'weighted_quadruped_with_leg_lift' => 20,
3496
'side_lying_leg_raise' => 21,
3497
'weighted_side_lying_leg_raise' => 22,
3498
'sliding_hip_adduction' => 23,
3499
'weighted_sliding_hip_adduction' => 24,
3500
'standing_adduction' => 25,
3501
'weighted_standing_adduction' => 26,
3502
'standing_cable_hip_abduction' => 27,
3503
'standing_hip_abduction' => 28,
3504
'weighted_standing_hip_abduction' => 29,
3505
'standing_rear_leg_raise' => 30,
3506
'weighted_standing_rear_leg_raise' => 31,
3507
'supine_hip_internal_rotation' => 32,
3508
'weighted_supine_hip_internal_rotation' => 33,
3509
},
3510
3511
'hip_swing_exercise_name' => +{
3512
'_base_type' => FIT_UINT16,
3513
'single_arm_kettlebell_swing' => 0,
3514
'single_arm_dumbbell_swing' => 1,
3515
'step_out_swing' => 2,
3516
},
3517
3518
'hyperextension_exercise_name' => +{
3519
'_base_type' => FIT_UINT16,
3520
'back_extension_with_opposite_arm_and_leg_reach' => 0,
3521
'weighted_back_extension_with_opposite_arm_and_leg_reach' => 1,
3522
'base_rotations' => 2,
3523
'weighted_base_rotations' => 3,
3524
'bent_knee_reverse_hyperextension' => 4,
3525
'weighted_bent_knee_reverse_hyperextension' => 5,
3526
'hollow_hold_and_roll' => 6,
3527
'weighted_hollow_hold_and_roll' => 7,
3528
'kicks' => 8,
3529
'weighted_kicks' => 9,
3530
'knee_raises' => 10,
3531
'weighted_knee_raises' => 11,
3532
'kneeling_superman' => 12,
3533
'weighted_kneeling_superman' => 13,
3534
'lat_pull_down_with_row' => 14,
3535
'medicine_ball_deadlift_to_reach' => 15,
3536
'one_arm_one_leg_row' => 16,
3537
'one_arm_row_with_band' => 17,
3538
'overhead_lunge_with_medicine_ball' => 18,
3539
'plank_knee_tucks' => 19,
3540
'weighted_plank_knee_tucks' => 20,
3541
'side_step' => 21,
3542
'weighted_side_step' => 22,
3543
'single_leg_back_extension' => 23,
3544
'weighted_single_leg_back_extension' => 24,
3545
'spine_extension' => 25,
3546
'weighted_spine_extension' => 26,
3547
'static_back_extension' => 27,
3548
'weighted_static_back_extension' => 28,
3549
'superman_from_floor' => 29,
3550
'weighted_superman_from_floor' => 30,
3551
'swiss_ball_back_extension' => 31,
3552
'weighted_swiss_ball_back_extension' => 32,
3553
'swiss_ball_hyperextension' => 33,
3554
'weighted_swiss_ball_hyperextension' => 34,
3555
'swiss_ball_opposite_arm_and_leg_lift' => 35,
3556
'weighted_swiss_ball_opposite_arm_and_leg_lift' => 36,
3557
'superman_on_swiss_ball' => 37,
3558
'cobra' => 38,
3559
'supine_floor_barre' => 39, # Deprecated do not use
3560
},
3561
3562
'lateral_raise_exercise_name' => +{
3563
'_base_type' => FIT_UINT16,
3564
'45_degree_cable_external_rotation' => 0,
3565
'alternating_lateral_raise_with_static_hold' => 1,
3566
'bar_muscle_up' => 2,
3567
'bent_over_lateral_raise' => 3,
3568
'cable_diagonal_raise' => 4,
3569
'cable_front_raise' => 5,
3570
'calorie_row' => 6,
3571
'combo_shoulder_raise' => 7,
3572
'dumbbell_diagonal_raise' => 8,
3573
'dumbbell_v_raise' => 9,
3574
'front_raise' => 10,
3575
'leaning_dumbbell_lateral_raise' => 11,
3576
'lying_dumbbell_raise' => 12,
3577
'muscle_up' => 13,
3578
'one_arm_cable_lateral_raise' => 14,
3579
'overhand_grip_rear_lateral_raise' => 15,
3580
'plate_raises' => 16,
3581
'ring_dip' => 17,
3582
'weighted_ring_dip' => 18,
3583
'ring_muscle_up' => 19,
3584
'weighted_ring_muscle_up' => 20,
3585
'rope_climb' => 21,
3586
'weighted_rope_climb' => 22,
3587
'scaption' => 23,
3588
'seated_lateral_raise' => 24,
3589
'seated_rear_lateral_raise' => 25,
3590
'side_lying_lateral_raise' => 26,
3591
'standing_lift' => 27,
3592
'suspended_row' => 28,
3593
'underhand_grip_rear_lateral_raise' => 29,
3594
'wall_slide' => 30,
3595
'weighted_wall_slide' => 31,
3596
'arm_circles' => 32,
3597
'shaving_the_head' => 33,
3598
},
3599
3600
'leg_curl_exercise_name' => +{
3601
'_base_type' => FIT_UINT16,
3602
'leg_curl' => 0,
3603
'weighted_leg_curl' => 1,
3604
'good_morning' => 2,
3605
'seated_barbell_good_morning' => 3,
3606
'single_leg_barbell_good_morning' => 4,
3607
'single_leg_sliding_leg_curl' => 5,
3608
'sliding_leg_curl' => 6,
3609
'split_barbell_good_morning' => 7,
3610
'split_stance_extension' => 8,
3611
'staggered_stance_good_morning' => 9,
3612
'swiss_ball_hip_raise_and_leg_curl' => 10,
3613
'zercher_good_morning' => 11,
3614
},
3615
3616
'leg_raise_exercise_name' => +{
3617
'_base_type' => FIT_UINT16,
3618
'hanging_knee_raise' => 0,
3619
'hanging_leg_raise' => 1,
3620
'weighted_hanging_leg_raise' => 2,
3621
'hanging_single_leg_raise' => 3,
3622
'weighted_hanging_single_leg_raise' => 4,
3623
'kettlebell_leg_raises' => 5,
3624
'leg_lowering_drill' => 6,
3625
'weighted_leg_lowering_drill' => 7,
3626
'lying_straight_leg_raise' => 8,
3627
'weighted_lying_straight_leg_raise' => 9,
3628
'medicine_ball_leg_drops' => 10,
3629
'quadruped_leg_raise' => 11,
3630
'weighted_quadruped_leg_raise' => 12,
3631
'reverse_leg_raise' => 13,
3632
'weighted_reverse_leg_raise' => 14,
3633
'reverse_leg_raise_on_swiss_ball' => 15,
3634
'weighted_reverse_leg_raise_on_swiss_ball' => 16,
3635
'single_leg_lowering_drill' => 17,
3636
'weighted_single_leg_lowering_drill' => 18,
3637
'weighted_hanging_knee_raise' => 19,
3638
'lateral_stepover' => 20,
3639
'weighted_lateral_stepover' => 21,
3640
},
3641
3642
'lunge_exercise_name' => +{
3643
'_base_type' => FIT_UINT16,
3644
'overhead_lunge' => 0,
3645
'lunge_matrix' => 1,
3646
'weighted_lunge_matrix' => 2,
3647
'alternating_barbell_forward_lunge' => 3,
3648
'alternating_dumbbell_lunge_with_reach' => 4,
3649
'back_foot_elevated_dumbbell_split_squat' => 5,
3650
'barbell_box_lunge' => 6,
3651
'barbell_bulgarian_split_squat' => 7,
3652
'barbell_crossover_lunge' => 8,
3653
'barbell_front_split_squat' => 9,
3654
'barbell_lunge' => 10,
3655
'barbell_reverse_lunge' => 11,
3656
'barbell_side_lunge' => 12,
3657
'barbell_split_squat' => 13,
3658
'core_control_rear_lunge' => 14,
3659
'diagonal_lunge' => 15,
3660
'drop_lunge' => 16,
3661
'dumbbell_box_lunge' => 17,
3662
'dumbbell_bulgarian_split_squat' => 18,
3663
'dumbbell_crossover_lunge' => 19,
3664
'dumbbell_diagonal_lunge' => 20,
3665
'dumbbell_lunge' => 21,
3666
'dumbbell_lunge_and_rotation' => 22,
3667
'dumbbell_overhead_bulgarian_split_squat' => 23,
3668
'dumbbell_reverse_lunge_to_high_knee_and_press' => 24,
3669
'dumbbell_side_lunge' => 25,
3670
'elevated_front_foot_barbell_split_squat' => 26,
3671
'front_foot_elevated_dumbbell_split_squat' => 27,
3672
'gunslinger_lunge' => 28,
3673
'lawnmower_lunge' => 29,
3674
'low_lunge_with_isometric_adduction' => 30,
3675
'low_side_to_side_lunge' => 31,
3676
'lunge' => 32,
3677
'weighted_lunge' => 33,
3678
'lunge_with_arm_reach' => 34,
3679
'lunge_with_diagonal_reach' => 35,
3680
'lunge_with_side_bend' => 36,
3681
'offset_dumbbell_lunge' => 37,
3682
'offset_dumbbell_reverse_lunge' => 38,
3683
'overhead_bulgarian_split_squat' => 39,
3684
'overhead_dumbbell_reverse_lunge' => 40,
3685
'overhead_dumbbell_split_squat' => 41,
3686
'overhead_lunge_with_rotation' => 42,
3687
'reverse_barbell_box_lunge' => 43,
3688
'reverse_box_lunge' => 44,
3689
'reverse_dumbbell_box_lunge' => 45,
3690
'reverse_dumbbell_crossover_lunge' => 46,
3691
'reverse_dumbbell_diagonal_lunge' => 47,
3692
'reverse_lunge_with_reach_back' => 48,
3693
'weighted_reverse_lunge_with_reach_back' => 49,
3694
'reverse_lunge_with_twist_and_overhead_reach' => 50,
3695
'weighted_reverse_lunge_with_twist_and_overhead_reach' => 51,
3696
'reverse_sliding_box_lunge' => 52,
3697
'weighted_reverse_sliding_box_lunge' => 53,
3698
'reverse_sliding_lunge' => 54,
3699
'weighted_reverse_sliding_lunge' => 55,
3700
'runners_lunge_to_balance' => 56,
3701
'weighted_runners_lunge_to_balance' => 57,
3702
'shifting_side_lunge' => 58,
3703
'side_and_crossover_lunge' => 59,
3704
'weighted_side_and_crossover_lunge' => 60,
3705
'side_lunge' => 61,
3706
'weighted_side_lunge' => 62,
3707
'side_lunge_and_press' => 63,
3708
'side_lunge_jump_off' => 64,
3709
'side_lunge_sweep' => 65,
3710
'weighted_side_lunge_sweep' => 66,
3711
'side_lunge_to_crossover_tap' => 67,
3712
'weighted_side_lunge_to_crossover_tap' => 68,
3713
'side_to_side_lunge_chops' => 69,
3714
'weighted_side_to_side_lunge_chops' => 70,
3715
'siff_jump_lunge' => 71,
3716
'weighted_siff_jump_lunge' => 72,
3717
'single_arm_reverse_lunge_and_press' => 73,
3718
'sliding_lateral_lunge' => 74,
3719
'weighted_sliding_lateral_lunge' => 75,
3720
'walking_barbell_lunge' => 76,
3721
'walking_dumbbell_lunge' => 77,
3722
'walking_lunge' => 78,
3723
'weighted_walking_lunge' => 79,
3724
'wide_grip_overhead_barbell_split_squat' => 80,
3725
},
3726
3727
'olympic_lift_exercise_name' => +{
3728
'_base_type' => FIT_UINT16,
3729
'barbell_hang_power_clean' => 0,
3730
'barbell_hang_squat_clean' => 1,
3731
'barbell_power_clean' => 2,
3732
'barbell_power_snatch' => 3,
3733
'barbell_squat_clean' => 4,
3734
'clean_and_jerk' => 5,
3735
'barbell_hang_power_snatch' => 6,
3736
'barbell_hang_pull' => 7,
3737
'barbell_high_pull' => 8,
3738
'barbell_snatch' => 9,
3739
'barbell_split_jerk' => 10,
3740
'clean' => 11,
3741
'dumbbell_clean' => 12,
3742
'dumbbell_hang_pull' => 13,
3743
'one_hand_dumbbell_split_snatch' => 14,
3744
'push_jerk' => 15,
3745
'single_arm_dumbbell_snatch' => 16,
3746
'single_arm_hang_snatch' => 17,
3747
'single_arm_kettlebell_snatch' => 18,
3748
'split_jerk' => 19,
3749
'squat_clean_and_jerk' => 20,
3750
},
3751
3752
'plank_exercise_name' => +{
3753
'_base_type' => FIT_UINT16,
3754
'45_degree_plank' => 0,
3755
'weighted_45_degree_plank' => 1,
3756
'90_degree_static_hold' => 2,
3757
'weighted_90_degree_static_hold' => 3,
3758
'bear_crawl' => 4,
3759
'weighted_bear_crawl' => 5,
3760
'cross_body_mountain_climber' => 6,
3761
'weighted_cross_body_mountain_climber' => 7,
3762
'elbow_plank_pike_jacks' => 8,
3763
'weighted_elbow_plank_pike_jacks' => 9,
3764
'elevated_feet_plank' => 10,
3765
'weighted_elevated_feet_plank' => 11,
3766
'elevator_abs' => 12,
3767
'weighted_elevator_abs' => 13,
3768
'extended_plank' => 14,
3769
'weighted_extended_plank' => 15,
3770
'full_plank_passe_twist' => 16,
3771
'weighted_full_plank_passe_twist' => 17,
3772
'inching_elbow_plank' => 18,
3773
'weighted_inching_elbow_plank' => 19,
3774
'inchworm_to_side_plank' => 20,
3775
'weighted_inchworm_to_side_plank' => 21,
3776
'kneeling_plank' => 22,
3777
'weighted_kneeling_plank' => 23,
3778
'kneeling_side_plank_with_leg_lift' => 24,
3779
'weighted_kneeling_side_plank_with_leg_lift' => 25,
3780
'lateral_roll' => 26,
3781
'weighted_lateral_roll' => 27,
3782
'lying_reverse_plank' => 28,
3783
'weighted_lying_reverse_plank' => 29,
3784
'medicine_ball_mountain_climber' => 30,
3785
'weighted_medicine_ball_mountain_climber' => 31,
3786
'modified_mountain_climber_and_extension' => 32,
3787
'weighted_modified_mountain_climber_and_extension' => 33,
3788
'mountain_climber' => 34,
3789
'weighted_mountain_climber' => 35,
3790
'mountain_climber_on_sliding_discs' => 36,
3791
'weighted_mountain_climber_on_sliding_discs' => 37,
3792
'mountain_climber_with_feet_on_bosu_ball' => 38,
3793
'weighted_mountain_climber_with_feet_on_bosu_ball' => 39,
3794
'mountain_climber_with_hands_on_bench' => 40,
3795
'mountain_climber_with_hands_on_swiss_ball' => 41,
3796
'weighted_mountain_climber_with_hands_on_swiss_ball' => 42,
3797
'plank' => 43,
3798
'plank_jacks_with_feet_on_sliding_discs' => 44,
3799
'weighted_plank_jacks_with_feet_on_sliding_discs' => 45,
3800
'plank_knee_twist' => 46,
3801
'weighted_plank_knee_twist' => 47,
3802
'plank_pike_jumps' => 48,
3803
'weighted_plank_pike_jumps' => 49,
3804
'plank_pikes' => 50,
3805
'weighted_plank_pikes' => 51,
3806
'plank_to_stand_up' => 52,
3807
'weighted_plank_to_stand_up' => 53,
3808
'plank_with_arm_raise' => 54,
3809
'weighted_plank_with_arm_raise' => 55,
3810
'plank_with_knee_to_elbow' => 56,
3811
'weighted_plank_with_knee_to_elbow' => 57,
3812
'plank_with_oblique_crunch' => 58,
3813
'weighted_plank_with_oblique_crunch' => 59,
3814
'plyometric_side_plank' => 60,
3815
'weighted_plyometric_side_plank' => 61,
3816
'rolling_side_plank' => 62,
3817
'weighted_rolling_side_plank' => 63,
3818
'side_kick_plank' => 64,
3819
'weighted_side_kick_plank' => 65,
3820
'side_plank' => 66,
3821
'weighted_side_plank' => 67,
3822
'side_plank_and_row' => 68,
3823
'weighted_side_plank_and_row' => 69,
3824
'side_plank_lift' => 70,
3825
'weighted_side_plank_lift' => 71,
3826
'side_plank_with_elbow_on_bosu_ball' => 72,
3827
'weighted_side_plank_with_elbow_on_bosu_ball' => 73,
3828
'side_plank_with_feet_on_bench' => 74,
3829
'weighted_side_plank_with_feet_on_bench' => 75,
3830
'side_plank_with_knee_circle' => 76,
3831
'weighted_side_plank_with_knee_circle' => 77,
3832
'side_plank_with_knee_tuck' => 78,
3833
'weighted_side_plank_with_knee_tuck' => 79,
3834
'side_plank_with_leg_lift' => 80,
3835
'weighted_side_plank_with_leg_lift' => 81,
3836
'side_plank_with_reach_under' => 82,
3837
'weighted_side_plank_with_reach_under' => 83,
3838
'single_leg_elevated_feet_plank' => 84,
3839
'weighted_single_leg_elevated_feet_plank' => 85,
3840
'single_leg_flex_and_extend' => 86,
3841
'weighted_single_leg_flex_and_extend' => 87,
3842
'single_leg_side_plank' => 88,
3843
'weighted_single_leg_side_plank' => 89,
3844
'spiderman_plank' => 90,
3845
'weighted_spiderman_plank' => 91,
3846
'straight_arm_plank' => 92,
3847
'weighted_straight_arm_plank' => 93,
3848
'straight_arm_plank_with_shoulder_touch' => 94,
3849
'weighted_straight_arm_plank_with_shoulder_touch' => 95,
3850
'swiss_ball_plank' => 96,
3851
'weighted_swiss_ball_plank' => 97,
3852
'swiss_ball_plank_leg_lift' => 98,
3853
'weighted_swiss_ball_plank_leg_lift' => 99,
3854
'swiss_ball_plank_leg_lift_and_hold' => 100,
3855
'swiss_ball_plank_with_feet_on_bench' => 101,
3856
'weighted_swiss_ball_plank_with_feet_on_bench' => 102,
3857
'swiss_ball_prone_jackknife' => 103,
3858
'weighted_swiss_ball_prone_jackknife' => 104,
3859
'swiss_ball_side_plank' => 105,
3860
'weighted_swiss_ball_side_plank' => 106,
3861
'three_way_plank' => 107,
3862
'weighted_three_way_plank' => 108,
3863
'towel_plank_and_knee_in' => 109,
3864
'weighted_towel_plank_and_knee_in' => 110,
3865
't_stabilization' => 111,
3866
'weighted_t_stabilization' => 112,
3867
'turkish_get_up_to_side_plank' => 113,
3868
'weighted_turkish_get_up_to_side_plank' => 114,
3869
'two_point_plank' => 115,
3870
'weighted_two_point_plank' => 116,
3871
'weighted_plank' => 117,
3872
'wide_stance_plank_with_diagonal_arm_lift' => 118,
3873
'weighted_wide_stance_plank_with_diagonal_arm_lift' => 119,
3874
'wide_stance_plank_with_diagonal_leg_lift' => 120,
3875
'weighted_wide_stance_plank_with_diagonal_leg_lift' => 121,
3876
'wide_stance_plank_with_leg_lift' => 122,
3877
'weighted_wide_stance_plank_with_leg_lift' => 123,
3878
'wide_stance_plank_with_opposite_arm_and_leg_lift' => 124,
3879
'weighted_mountain_climber_with_hands_on_bench' => 125,
3880
'weighted_swiss_ball_plank_leg_lift_and_hold' => 126,
3881
'weighted_wide_stance_plank_with_opposite_arm_and_leg_lift' => 127,
3882
'plank_with_feet_on_swiss_ball' => 128,
3883
'side_plank_to_plank_with_reach_under' => 129,
3884
'bridge_with_glute_lower_lift' => 130,
3885
'bridge_one_leg_bridge' => 131,
3886
'plank_with_arm_variations' => 132,
3887
'plank_with_leg_lift' => 133,
3888
'reverse_plank_with_leg_pull' => 134,
3889
},
3890
3891
'plyo_exercise_name' => +{
3892
'_base_type' => FIT_UINT16,
3893
'alternating_jump_lunge' => 0,
3894
'weighted_alternating_jump_lunge' => 1,
3895
'barbell_jump_squat' => 2,
3896
'body_weight_jump_squat' => 3,
3897
'weighted_jump_squat' => 4,
3898
'cross_knee_strike' => 5,
3899
'weighted_cross_knee_strike' => 6,
3900
'depth_jump' => 7,
3901
'weighted_depth_jump' => 8,
3902
'dumbbell_jump_squat' => 9,
3903
'dumbbell_split_jump' => 10,
3904
'front_knee_strike' => 11,
3905
'weighted_front_knee_strike' => 12,
3906
'high_box_jump' => 13,
3907
'weighted_high_box_jump' => 14,
3908
'isometric_explosive_body_weight_jump_squat' => 15,
3909
'weighted_isometric_explosive_jump_squat' => 16,
3910
'lateral_leap_and_hop' => 17,
3911
'weighted_lateral_leap_and_hop' => 18,
3912
'lateral_plyo_squats' => 19,
3913
'weighted_lateral_plyo_squats' => 20,
3914
'lateral_slide' => 21,
3915
'weighted_lateral_slide' => 22,
3916
'medicine_ball_overhead_throws' => 23,
3917
'medicine_ball_side_throw' => 24,
3918
'medicine_ball_slam' => 25,
3919
'side_to_side_medicine_ball_throws' => 26,
3920
'side_to_side_shuffle_jump' => 27,
3921
'weighted_side_to_side_shuffle_jump' => 28,
3922
'squat_jump_onto_box' => 29,
3923
'weighted_squat_jump_onto_box' => 30,
3924
'squat_jumps_in_and_out' => 31,
3925
'weighted_squat_jumps_in_and_out' => 32,
3926
},
3927
3928
'pull_up_exercise_name' => +{
3929
'_base_type' => FIT_UINT16,
3930
'banded_pull_ups' => 0,
3931
'30_degree_lat_pulldown' => 1,
3932
'band_assisted_chin_up' => 2,
3933
'close_grip_chin_up' => 3,
3934
'weighted_close_grip_chin_up' => 4,
3935
'close_grip_lat_pulldown' => 5,
3936
'crossover_chin_up' => 6,
3937
'weighted_crossover_chin_up' => 7,
3938
'ez_bar_pullover' => 8,
3939
'hanging_hurdle' => 9,
3940
'weighted_hanging_hurdle' => 10,
3941
'kneeling_lat_pulldown' => 11,
3942
'kneeling_underhand_grip_lat_pulldown' => 12,
3943
'lat_pulldown' => 13,
3944
'mixed_grip_chin_up' => 14,
3945
'weighted_mixed_grip_chin_up' => 15,
3946
'mixed_grip_pull_up' => 16,
3947
'weighted_mixed_grip_pull_up' => 17,
3948
'reverse_grip_pulldown' => 18,
3949
'standing_cable_pullover' => 19,
3950
'straight_arm_pulldown' => 20,
3951
'swiss_ball_ez_bar_pullover' => 21,
3952
'towel_pull_up' => 22,
3953
'weighted_towel_pull_up' => 23,
3954
'weighted_pull_up' => 24,
3955
'wide_grip_lat_pulldown' => 25,
3956
'wide_grip_pull_up' => 26,
3957
'weighted_wide_grip_pull_up' => 27,
3958
'burpee_pull_up' => 28,
3959
'weighted_burpee_pull_up' => 29,
3960
'jumping_pull_ups' => 30,
3961
'weighted_jumping_pull_ups' => 31,
3962
'kipping_pull_up' => 32,
3963
'weighted_kipping_pull_up' => 33,
3964
'l_pull_up' => 34,
3965
'weighted_l_pull_up' => 35,
3966
'suspended_chin_up' => 36,
3967
'weighted_suspended_chin_up' => 37,
3968
'pull_up' => 38,
3969
},
3970
3971
'push_up_exercise_name' => +{
3972
'_base_type' => FIT_UINT16,
3973
'chest_press_with_band' => 0,
3974
'alternating_staggered_push_up' => 1,
3975
'weighted_alternating_staggered_push_up' => 2,
3976
'alternating_hands_medicine_ball_push_up' => 3,
3977
'weighted_alternating_hands_medicine_ball_push_up' => 4,
3978
'bosu_ball_push_up' => 5,
3979
'weighted_bosu_ball_push_up' => 6,
3980
'clapping_push_up' => 7,
3981
'weighted_clapping_push_up' => 8,
3982
'close_grip_medicine_ball_push_up' => 9,
3983
'weighted_close_grip_medicine_ball_push_up' => 10,
3984
'close_hands_push_up' => 11,
3985
'weighted_close_hands_push_up' => 12,
3986
'decline_push_up' => 13,
3987
'weighted_decline_push_up' => 14,
3988
'diamond_push_up' => 15,
3989
'weighted_diamond_push_up' => 16,
3990
'explosive_crossover_push_up' => 17,
3991
'weighted_explosive_crossover_push_up' => 18,
3992
'explosive_push_up' => 19,
3993
'weighted_explosive_push_up' => 20,
3994
'feet_elevated_side_to_side_push_up' => 21,
3995
'weighted_feet_elevated_side_to_side_push_up' => 22,
3996
'hand_release_push_up' => 23,
3997
'weighted_hand_release_push_up' => 24,
3998
'handstand_push_up' => 25,
3999
'weighted_handstand_push_up' => 26,
4000
'incline_push_up' => 27,
4001
'weighted_incline_push_up' => 28,
4002
'isometric_explosive_push_up' => 29,
4003
'weighted_isometric_explosive_push_up' => 30,
4004
'judo_push_up' => 31,
4005
'weighted_judo_push_up' => 32,
4006
'kneeling_push_up' => 33,
4007
'weighted_kneeling_push_up' => 34,
4008
'medicine_ball_chest_pass' => 35,
4009
'medicine_ball_push_up' => 36,
4010
'weighted_medicine_ball_push_up' => 37,
4011
'one_arm_push_up' => 38,
4012
'weighted_one_arm_push_up' => 39,
4013
'weighted_push_up' => 40,
4014
'push_up_and_row' => 41,
4015
'weighted_push_up_and_row' => 42,
4016
'push_up_plus' => 43,
4017
'weighted_push_up_plus' => 44,
4018
'push_up_with_feet_on_swiss_ball' => 45,
4019
'weighted_push_up_with_feet_on_swiss_ball' => 46,
4020
'push_up_with_one_hand_on_medicine_ball' => 47,
4021
'weighted_push_up_with_one_hand_on_medicine_ball' => 48,
4022
'shoulder_push_up' => 49,
4023
'weighted_shoulder_push_up' => 50,
4024
'single_arm_medicine_ball_push_up' => 51,
4025
'weighted_single_arm_medicine_ball_push_up' => 52,
4026
'spiderman_push_up' => 53,
4027
'weighted_spiderman_push_up' => 54,
4028
'stacked_feet_push_up' => 55,
4029
'weighted_stacked_feet_push_up' => 56,
4030
'staggered_hands_push_up' => 57,
4031
'weighted_staggered_hands_push_up' => 58,
4032
'suspended_push_up' => 59,
4033
'weighted_suspended_push_up' => 60,
4034
'swiss_ball_push_up' => 61,
4035
'weighted_swiss_ball_push_up' => 62,
4036
'swiss_ball_push_up_plus' => 63,
4037
'weighted_swiss_ball_push_up_plus' => 64,
4038
't_push_up' => 65,
4039
'weighted_t_push_up' => 66,
4040
'triple_stop_push_up' => 67,
4041
'weighted_triple_stop_push_up' => 68,
4042
'wide_hands_push_up' => 69,
4043
'weighted_wide_hands_push_up' => 70,
4044
'parallette_handstand_push_up' => 71,
4045
'weighted_parallette_handstand_push_up' => 72,
4046
'ring_handstand_push_up' => 73,
4047
'weighted_ring_handstand_push_up' => 74,
4048
'ring_push_up' => 75,
4049
'weighted_ring_push_up' => 76,
4050
'push_up' => 77,
4051
'pilates_pushup' => 78,
4052
},
4053
4054
'row_exercise_name' => +{
4055
'_base_type' => FIT_UINT16,
4056
'barbell_straight_leg_deadlift_to_row' => 0,
4057
'cable_row_standing' => 1,
4058
'dumbbell_row' => 2,
4059
'elevated_feet_inverted_row' => 3,
4060
'weighted_elevated_feet_inverted_row' => 4,
4061
'face_pull' => 5,
4062
'face_pull_with_external_rotation' => 6,
4063
'inverted_row_with_feet_on_swiss_ball' => 7,
4064
'weighted_inverted_row_with_feet_on_swiss_ball' => 8,
4065
'kettlebell_row' => 9,
4066
'modified_inverted_row' => 10,
4067
'weighted_modified_inverted_row' => 11,
4068
'neutral_grip_alternating_dumbbell_row' => 12,
4069
'one_arm_bent_over_row' => 13,
4070
'one_legged_dumbbell_row' => 14,
4071
'renegade_row' => 15,
4072
'reverse_grip_barbell_row' => 16,
4073
'rope_handle_cable_row' => 17,
4074
'seated_cable_row' => 18,
4075
'seated_dumbbell_row' => 19,
4076
'single_arm_cable_row' => 20,
4077
'single_arm_cable_row_and_rotation' => 21,
4078
'single_arm_inverted_row' => 22,
4079
'weighted_single_arm_inverted_row' => 23,
4080
'single_arm_neutral_grip_dumbbell_row' => 24,
4081
'single_arm_neutral_grip_dumbbell_row_and_rotation' => 25,
4082
'suspended_inverted_row' => 26,
4083
'weighted_suspended_inverted_row' => 27,
4084
't_bar_row' => 28,
4085
'towel_grip_inverted_row' => 29,
4086
'weighted_towel_grip_inverted_row' => 30,
4087
'underhand_grip_cable_row' => 31,
4088
'v_grip_cable_row' => 32,
4089
'wide_grip_seated_cable_row' => 33,
4090
},
4091
4092
'shoulder_press_exercise_name' => +{
4093
'_base_type' => FIT_UINT16,
4094
'alternating_dumbbell_shoulder_press' => 0,
4095
'arnold_press' => 1,
4096
'barbell_front_squat_to_push_press' => 2,
4097
'barbell_push_press' => 3,
4098
'barbell_shoulder_press' => 4,
4099
'dead_curl_press' => 5,
4100
'dumbbell_alternating_shoulder_press_and_twist' => 6,
4101
'dumbbell_hammer_curl_to_lunge_to_press' => 7,
4102
'dumbbell_push_press' => 8,
4103
'floor_inverted_shoulder_press' => 9,
4104
'weighted_floor_inverted_shoulder_press' => 10,
4105
'inverted_shoulder_press' => 11,
4106
'weighted_inverted_shoulder_press' => 12,
4107
'one_arm_push_press' => 13,
4108
'overhead_barbell_press' => 14,
4109
'overhead_dumbbell_press' => 15,
4110
'seated_barbell_shoulder_press' => 16,
4111
'seated_dumbbell_shoulder_press' => 17,
4112
'single_arm_dumbbell_shoulder_press' => 18,
4113
'single_arm_step_up_and_press' => 19,
4114
'smith_machine_overhead_press' => 20,
4115
'split_stance_hammer_curl_to_press' => 21,
4116
'swiss_ball_dumbbell_shoulder_press' => 22,
4117
'weight_plate_front_raise' => 23,
4118
},
4119
4120
'shoulder_stability_exercise_name' => +{
4121
'_base_type' => FIT_UINT16,
4122
'90_degree_cable_external_rotation' => 0,
4123
'band_external_rotation' => 1,
4124
'band_internal_rotation' => 2,
4125
'bent_arm_lateral_raise_and_external_rotation' => 3,
4126
'cable_external_rotation' => 4,
4127
'dumbbell_face_pull_with_external_rotation' => 5,
4128
'floor_i_raise' => 6,
4129
'weighted_floor_i_raise' => 7,
4130
'floor_t_raise' => 8,
4131
'weighted_floor_t_raise' => 9,
4132
'floor_y_raise' => 10,
4133
'weighted_floor_y_raise' => 11,
4134
'incline_i_raise' => 12,
4135
'weighted_incline_i_raise' => 13,
4136
'incline_l_raise' => 14,
4137
'weighted_incline_l_raise' => 15,
4138
'incline_t_raise' => 16,
4139
'weighted_incline_t_raise' => 17,
4140
'incline_w_raise' => 18,
4141
'weighted_incline_w_raise' => 19,
4142
'incline_y_raise' => 20,
4143
'weighted_incline_y_raise' => 21,
4144
'lying_external_rotation' => 22,
4145
'seated_dumbbell_external_rotation' => 23,
4146
'standing_l_raise' => 24,
4147
'swiss_ball_i_raise' => 25,
4148
'weighted_swiss_ball_i_raise' => 26,
4149
'swiss_ball_t_raise' => 27,
4150
'weighted_swiss_ball_t_raise' => 28,
4151
'swiss_ball_w_raise' => 29,
4152
'weighted_swiss_ball_w_raise' => 30,
4153
'swiss_ball_y_raise' => 31,
4154
'weighted_swiss_ball_y_raise' => 32,
4155
},
4156
4157
'shrug_exercise_name' => +{
4158
'_base_type' => FIT_UINT16,
4159
'barbell_jump_shrug' => 0,
4160
'barbell_shrug' => 1,
4161
'barbell_upright_row' => 2,
4162
'behind_the_back_smith_machine_shrug' => 3,
4163
'dumbbell_jump_shrug' => 4,
4164
'dumbbell_shrug' => 5,
4165
'dumbbell_upright_row' => 6,
4166
'incline_dumbbell_shrug' => 7,
4167
'overhead_barbell_shrug' => 8,
4168
'overhead_dumbbell_shrug' => 9,
4169
'scaption_and_shrug' => 10,
4170
'scapular_retraction' => 11,
4171
'serratus_chair_shrug' => 12,
4172
'weighted_serratus_chair_shrug' => 13,
4173
'serratus_shrug' => 14,
4174
'weighted_serratus_shrug' => 15,
4175
'wide_grip_jump_shrug' => 16,
4176
},
4177
4178
'sit_up_exercise_name' => +{
4179
'_base_type' => FIT_UINT16,
4180
'alternating_sit_up' => 0,
4181
'weighted_alternating_sit_up' => 1,
4182
'bent_knee_v_up' => 2,
4183
'weighted_bent_knee_v_up' => 3,
4184
'butterfly_sit_up' => 4,
4185
'weighted_butterfly_situp' => 5,
4186
'cross_punch_roll_up' => 6,
4187
'weighted_cross_punch_roll_up' => 7,
4188
'crossed_arms_sit_up' => 8,
4189
'weighted_crossed_arms_sit_up' => 9,
4190
'get_up_sit_up' => 10,
4191
'weighted_get_up_sit_up' => 11,
4192
'hovering_sit_up' => 12,
4193
'weighted_hovering_sit_up' => 13,
4194
'kettlebell_sit_up' => 14,
4195
'medicine_ball_alternating_v_up' => 15,
4196
'medicine_ball_sit_up' => 16,
4197
'medicine_ball_v_up' => 17,
4198
'modified_sit_up' => 18,
4199
'negative_sit_up' => 19,
4200
'one_arm_full_sit_up' => 20,
4201
'reclining_circle' => 21,
4202
'weighted_reclining_circle' => 22,
4203
'reverse_curl_up' => 23,
4204
'weighted_reverse_curl_up' => 24,
4205
'single_leg_swiss_ball_jackknife' => 25,
4206
'weighted_single_leg_swiss_ball_jackknife' => 26,
4207
'the_teaser' => 27,
4208
'the_teaser_weighted' => 28,
4209
'three_part_roll_down' => 29,
4210
'weighted_three_part_roll_down' => 30,
4211
'v_up' => 31,
4212
'weighted_v_up' => 32,
4213
'weighted_russian_twist_on_swiss_ball' => 33,
4214
'weighted_sit_up' => 34,
4215
'x_abs' => 35,
4216
'weighted_x_abs' => 36,
4217
'sit_up' => 37,
4218
},
4219
4220
'squat_exercise_name' => +{
4221
'_base_type' => FIT_UINT16,
4222
'leg_press' => 0,
4223
'back_squat_with_body_bar' => 1,
4224
'back_squats' => 2,
4225
'weighted_back_squats' => 3,
4226
'balancing_squat' => 4,
4227
'weighted_balancing_squat' => 5,
4228
'barbell_back_squat' => 6,
4229
'barbell_box_squat' => 7,
4230
'barbell_front_squat' => 8,
4231
'barbell_hack_squat' => 9,
4232
'barbell_hang_squat_snatch' => 10,
4233
'barbell_lateral_step_up' => 11,
4234
'barbell_quarter_squat' => 12,
4235
'barbell_siff_squat' => 13,
4236
'barbell_squat_snatch' => 14,
4237
'barbell_squat_with_heels_raised' => 15,
4238
'barbell_stepover' => 16,
4239
'barbell_step_up' => 17,
4240
'bench_squat_with_rotational_chop' => 18,
4241
'weighted_bench_squat_with_rotational_chop' => 19,
4242
'body_weight_wall_squat' => 20,
4243
'weighted_wall_squat' => 21,
4244
'box_step_squat' => 22,
4245
'weighted_box_step_squat' => 23,
4246
'braced_squat' => 24,
4247
'crossed_arm_barbell_front_squat' => 25,
4248
'crossover_dumbbell_step_up' => 26,
4249
'dumbbell_front_squat' => 27,
4250
'dumbbell_split_squat' => 28,
4251
'dumbbell_squat' => 29,
4252
'dumbbell_squat_clean' => 30,
4253
'dumbbell_stepover' => 31,
4254
'dumbbell_step_up' => 32,
4255
'elevated_single_leg_squat' => 33,
4256
'weighted_elevated_single_leg_squat' => 34,
4257
'figure_four_squats' => 35,
4258
'weighted_figure_four_squats' => 36,
4259
'goblet_squat' => 37,
4260
'kettlebell_squat' => 38,
4261
'kettlebell_swing_overhead' => 39,
4262
'kettlebell_swing_with_flip_to_squat' => 40,
4263
'lateral_dumbbell_step_up' => 41,
4264
'one_legged_squat' => 42,
4265
'overhead_dumbbell_squat' => 43,
4266
'overhead_squat' => 44,
4267
'partial_single_leg_squat' => 45,
4268
'weighted_partial_single_leg_squat' => 46,
4269
'pistol_squat' => 47,
4270
'weighted_pistol_squat' => 48,
4271
'plie_slides' => 49,
4272
'weighted_plie_slides' => 50,
4273
'plie_squat' => 51,
4274
'weighted_plie_squat' => 52,
4275
'prisoner_squat' => 53,
4276
'weighted_prisoner_squat' => 54,
4277
'single_leg_bench_get_up' => 55,
4278
'weighted_single_leg_bench_get_up' => 56,
4279
'single_leg_bench_squat' => 57,
4280
'weighted_single_leg_bench_squat' => 58,
4281
'single_leg_squat_on_swiss_ball' => 59,
4282
'weighted_single_leg_squat_on_swiss_ball' => 60,
4283
'squat' => 61,
4284
'weighted_squat' => 62,
4285
'squats_with_band' => 63,
4286
'staggered_squat' => 64,
4287
'weighted_staggered_squat' => 65,
4288
'step_up' => 66,
4289
'weighted_step_up' => 67,
4290
'suitcase_squats' => 68,
4291
'sumo_squat' => 69,
4292
'sumo_squat_slide_in' => 70,
4293
'weighted_sumo_squat_slide_in' => 71,
4294
'sumo_squat_to_high_pull' => 72,
4295
'sumo_squat_to_stand' => 73,
4296
'weighted_sumo_squat_to_stand' => 74,
4297
'sumo_squat_with_rotation' => 75,
4298
'weighted_sumo_squat_with_rotation' => 76,
4299
'swiss_ball_body_weight_wall_squat' => 77,
4300
'weighted_swiss_ball_wall_squat' => 78,
4301
'thrusters' => 79,
4302
'uneven_squat' => 80,
4303
'weighted_uneven_squat' => 81,
4304
'waist_slimming_squat' => 82,
4305
'wall_ball' => 83,
4306
'wide_stance_barbell_squat' => 84,
4307
'wide_stance_goblet_squat' => 85,
4308
'zercher_squat' => 86,
4309
'kbs_overhead' => 87, # Deprecated do not use
4310
'squat_and_side_kick' => 88,
4311
'squat_jumps_in_n_out' => 89,
4312
'pilates_plie_squats_parallel_turned_out_flat_and_heels' => 90,
4313
'releve_straight_leg_and_knee_bent_with_one_leg_variation' => 91,
4314
},
4315
4316
'total_body_exercise_name' => +{
4317
'_base_type' => FIT_UINT16,
4318
'burpee' => 0,
4319
'weighted_burpee' => 1,
4320
'burpee_box_jump' => 2,
4321
'weighted_burpee_box_jump' => 3,
4322
'high_pull_burpee' => 4,
4323
'man_makers' => 5,
4324
'one_arm_burpee' => 6,
4325
'squat_thrusts' => 7,
4326
'weighted_squat_thrusts' => 8,
4327
'squat_plank_push_up' => 9,
4328
'weighted_squat_plank_push_up' => 10,
4329
'standing_t_rotation_balance' => 11,
4330
'weighted_standing_t_rotation_balance' => 12,
4331
},
4332
4333
'triceps_extension_exercise_name' => +{
4334
'_base_type' => FIT_UINT16,
4335
'bench_dip' => 0,
4336
'weighted_bench_dip' => 1,
4337
'body_weight_dip' => 2,
4338
'cable_kickback' => 3,
4339
'cable_lying_triceps_extension' => 4,
4340
'cable_overhead_triceps_extension' => 5,
4341
'dumbbell_kickback' => 6,
4342
'dumbbell_lying_triceps_extension' => 7,
4343
'ez_bar_overhead_triceps_extension' => 8,
4344
'incline_dip' => 9,
4345
'weighted_incline_dip' => 10,
4346
'incline_ez_bar_lying_triceps_extension' => 11,
4347
'lying_dumbbell_pullover_to_extension' => 12,
4348
'lying_ez_bar_triceps_extension' => 13,
4349
'lying_triceps_extension_to_close_grip_bench_press' => 14,
4350
'overhead_dumbbell_triceps_extension' => 15,
4351
'reclining_triceps_press' => 16,
4352
'reverse_grip_pressdown' => 17,
4353
'reverse_grip_triceps_pressdown' => 18,
4354
'rope_pressdown' => 19,
4355
'seated_barbell_overhead_triceps_extension' => 20,
4356
'seated_dumbbell_overhead_triceps_extension' => 21,
4357
'seated_ez_bar_overhead_triceps_extension' => 22,
4358
'seated_single_arm_overhead_dumbbell_extension' => 23,
4359
'single_arm_dumbbell_overhead_triceps_extension' => 24,
4360
'single_dumbbell_seated_overhead_triceps_extension' => 25,
4361
'single_leg_bench_dip_and_kick' => 26,
4362
'weighted_single_leg_bench_dip_and_kick' => 27,
4363
'single_leg_dip' => 28,
4364
'weighted_single_leg_dip' => 29,
4365
'static_lying_triceps_extension' => 30,
4366
'suspended_dip' => 31,
4367
'weighted_suspended_dip' => 32,
4368
'swiss_ball_dumbbell_lying_triceps_extension' => 33,
4369
'swiss_ball_ez_bar_lying_triceps_extension' => 34,
4370
'swiss_ball_ez_bar_overhead_triceps_extension' => 35,
4371
'tabletop_dip' => 36,
4372
'weighted_tabletop_dip' => 37,
4373
'triceps_extension_on_floor' => 38,
4374
'triceps_pressdown' => 39,
4375
'weighted_dip' => 40,
4376
},
4377
4378
'warm_up_exercise_name' => +{
4379
'_base_type' => FIT_UINT16,
4380
'quadruped_rocking' => 0,
4381
'neck_tilts' => 1,
4382
'ankle_circles' => 2,
4383
'ankle_dorsiflexion_with_band' => 3,
4384
'ankle_internal_rotation' => 4,
4385
'arm_circles' => 5,
4386
'bent_over_reach_to_sky' => 6,
4387
'cat_camel' => 7,
4388
'elbow_to_foot_lunge' => 8,
4389
'forward_and_backward_leg_swings' => 9,
4390
'groiners' => 10,
4391
'inverted_hamstring_stretch' => 11,
4392
'lateral_duck_under' => 12,
4393
'neck_rotations' => 13,
4394
'opposite_arm_and_leg_balance' => 14,
4395
'reach_roll_and_lift' => 15,
4396
'scorpion' => 16, # Deprecated do not use
4397
'shoulder_circles' => 17,
4398
'side_to_side_leg_swings' => 18,
4399
'sleeper_stretch' => 19,
4400
'slide_out' => 20,
4401
'swiss_ball_hip_crossover' => 21,
4402
'swiss_ball_reach_roll_and_lift' => 22,
4403
'swiss_ball_windshield_wipers' => 23,
4404
'thoracic_rotation' => 24,
4405
'walking_high_kicks' => 25,
4406
'walking_high_knees' => 26,
4407
'walking_knee_hugs' => 27,
4408
'walking_leg_cradles' => 28,
4409
'walkout' => 29,
4410
'walkout_from_push_up_position' => 30,
4411
},
4412
4413
'run_exercise_name' => +{
4414
'_base_type' => FIT_UINT16,
4415
'run' => 0,
4416
'walk' => 1,
4417
'jog' => 2,
4418
'sprint' => 3,
4419
},
4420
4421
'water_type' => +{
4422
'_base_type' => FIT_ENUM,
4423
'fresh' => 0,
4424
'salt' => 1,
4425
'en13319' => 2,
4426
'custom' => 3,
4427
},
4428
4429
'tissue_model_type' => +{
4430
'_base_type' => FIT_ENUM,
4431
'zhl_16c' => 0, # Buhlmann's decompression algorithm, version C
4432
},
4433
4434
'dive_gas_status' => +{
4435
'_base_type' => FIT_ENUM,
4436
'disabled' => 0,
4437
'enabled' => 1,
4438
'backup_only' => 2,
4439
},
4440
4441
'dive_alert' => +{
4442
'_base_type' => FIT_ENUM,
4443
'ndl_reached' => 0,
4444
'gas_switch_prompted' => 1,
4445
'near_surface' => 2,
4446
'approaching_ndl' => 3,
4447
'po2_warn' => 4,
4448
'po2_crit_high' => 5,
4449
'po2_crit_low' => 6,
4450
'time_alert' => 7,
4451
'depth_alert' => 8,
4452
'deco_ceiling_broken' => 9,
4453
'deco_complete' => 10,
4454
'safety_stop_broken' => 11,
4455
'safety_stop_complete' => 12,
4456
'cns_warning' => 13,
4457
'cns_critical' => 14,
4458
'otu_warning' => 15,
4459
'otu_critical' => 16,
4460
'ascent_critical' => 17,
4461
'alert_dismissed_by_key' => 18,
4462
'alert_dismissed_by_timeout' => 19,
4463
'battery_low' => 20,
4464
'battery_critical' => 21,
4465
'safety_stop_started' => 22,
4466
'approaching_first_deco_stop' => 23,
4467
'setpoint_switch_auto_low' => 24,
4468
'setpoint_switch_auto_high' => 25,
4469
'setpoint_switch_manual_low' => 26,
4470
'setpoint_switch_manual_high' => 27,
4471
'auto_setpoint_switch_ignored' => 28,
4472
'switched_to_open_circuit' => 29,
4473
'switched_to_closed_circuit' => 30,
4474
'tank_battery_low' => 32,
4475
'po2_ccr_dil_low' => 33, # ccr diluent has low po2
4476
'deco_stop_cleared' => 34, # a deco stop has been cleared
4477
'apnea_neutral_buoyancy' => 35, # Target Depth Apnea Alarm triggered
4478
'apnea_target_depth' => 36, # Neutral Buoyance Apnea Alarm triggered
4479
'apnea_surface' => 37, # Surface Apnea Alarm triggered
4480
'apnea_high_speed' => 38, # High Speed Apnea Alarm triggered
4481
'apnea_low_speed' => 39, # Low Speed Apnea Alarm triggered
4482
},
4483
4484
'dive_alarm_type' => +{
4485
'_base_type' => FIT_ENUM,
4486
'depth' => 0,
4487
'time' => 1,
4488
'speed' => 2, # Alarm when a certain ascent or descent rate is exceeded
4489
},
4490
4491
'dive_backlight_mode' => +{
4492
'_base_type' => FIT_ENUM,
4493
'at_depth' => 0,
4494
'always_on' => 1,
4495
},
4496
4497
'sleep_level' => +{
4498
'_base_type' => FIT_ENUM,
4499
'unmeasurable' => 0,
4500
'awake' => 1,
4501
'light' => 2,
4502
'deep' => 3,
4503
'rem' => 4,
4504
},
4505
4506
'spo2_measurement_type' => +{
4507
'_base_type' => FIT_ENUM,
4508
'off_wrist' => 0,
4509
'spot_check' => 1,
4510
'continuous_check' => 2,
4511
'periodic' => 3,
4512
},
4513
4514
'ccr_setpoint_switch_mode' => +{
4515
'_base_type' => FIT_ENUM,
4516
'manual' => 0, # User switches setpoints manually
4517
'automatic' => 1, # Switch automatically based on depth
4518
},
4519
4520
'dive_gas_mode' => +{
4521
'_base_type' => FIT_ENUM,
4522
'open_circuit' => 0,
4523
'closed_circuit_diluent' => 1,
4524
},
4525
4526
'projectile_type' => +{
4527
'_base_type' => FIT_ENUM,
4528
'arrow' => 0, # Arrow projectile type
4529
'rifle_cartridge' => 1, # Rifle cartridge projectile type
4530
'pistol_cartridge' => 2, # Pistol cartridge projectile type
4531
'shotshell' => 3, # Shotshell projectile type
4532
'air_rifle_pellet' => 4, # Air rifle pellet projectile type
4533
'other' => 5, # Other projectile type
4534
},
4535
4536
'favero_product' => +{
4537
'_base_type' => FIT_UINT16,
4538
'assioma_uno' => 10,
4539
'assioma_duo' => 12,
4540
},
4541
4542
'split_type' => +{
4543
'_base_type' => FIT_ENUM,
4544
'ascent_split' => 1,
4545
'descent_split' => 2,
4546
'interval_active' => 3,
4547
'interval_rest' => 4,
4548
'interval_warmup' => 5,
4549
'interval_cooldown' => 6,
4550
'interval_recovery' => 7,
4551
'interval_other' => 8,
4552
'climb_active' => 9,
4553
'climb_rest' => 10,
4554
'surf_active' => 11,
4555
'run_active' => 12,
4556
'run_rest' => 13,
4557
'workout_round' => 14,
4558
'rwd_run' => 17, # run/walk detection running
4559
'rwd_walk' => 18, # run/walk detection walking
4560
'windsurf_active' => 21,
4561
'rwd_stand' => 22, # run/walk detection standing
4562
'transition' => 23, # Marks the time going from ascent_split to descent_split/used in backcountry ski
4563
'ski_lift_split' => 28,
4564
'ski_run_split' => 29,
4565
},
4566
4567
'climb_pro_event' => +{
4568
'_base_type' => FIT_ENUM,
4569
'approach' => 0,
4570
'start' => 1,
4571
'complete' => 2,
4572
},
4573
4574
'gas_consumption_rate_type' => +{
4575
'_base_type' => FIT_ENUM,
4576
'pressure_sac' => 0, # Pressure-based Surface Air Consumption
4577
'volume_sac' => 1, # Volumetric Surface Air Consumption
4578
'rmv' => 2, # Respiratory Minute Volume
4579
},
4580
4581
'tap_sensitivity' => +{
4582
'_base_type' => FIT_ENUM,
4583
'high' => 0,
4584
'medium' => 1,
4585
'low' => 2,
4586
},
4587
4588
'radar_threat_level_type' => +{
4589
'_base_type' => FIT_ENUM,
4590
'threat_unknown' => 0,
4591
'threat_none' => 1,
4592
'threat_approaching' => 2,
4593
'threat_approaching_fast' => 3,
4594
},
4595
4596
'max_met_speed_source' => +{
4597
'_base_type' => FIT_ENUM,
4598
'onboard_gps' => 0,
4599
'connected_gps' => 1,
4600
'cadence' => 2,
4601
},
4602
4603
'max_met_heart_rate_source' => +{
4604
'_base_type' => FIT_ENUM,
4605
'whr' => 0, # Wrist Heart Rate Monitor
4606
'hrm' => 1, # Chest Strap Heart Rate Monitor
4607
},
4608
4609
'hrv_status' => +{
4610
'_base_type' => FIT_ENUM,
4611
'none' => 0,
4612
'poor' => 1,
4613
'low' => 2,
4614
'unbalanced' => 3,
4615
'balanced' => 4,
4616
},
4617
4618
'no_fly_time_mode' => +{
4619
'_base_type' => FIT_ENUM,
4620
'standard' => 0, # Standard Diver Alert Network no-fly guidance
4621
'flat_24_hours' => 1, # Flat 24 hour no-fly guidance
4622
},
4623
4624
);
4625
4626
for my $typenam (keys %named_type) { # if a type was _moved_to, copy the new href to $named_type{$typenam}
4627
my $typedesc = $named_type{$typenam};
4628
if (defined $typedesc->{_moved_to} and $typedesc->{_moved_to} ne '') {
4629
if ($typenam ne 'device_type') { $DB::single=1 } # want to know if it applies to others
4630
my $to = $named_type{$typedesc->{_moved_to}};
4631
$named_type{$typenam} = {%$to} if ref $to eq 'HASH'
4632
}
4633
}
4634
while (my ($typenam, $typedesc) = each %named_type) {
4635
# copy and flip key/value pairs of all hrefs in %named_type (except _base_type, _mask, …)
4636
for my $name (grep {!/^_/} keys %$typedesc) {
4637
$typedesc->{$typedesc->{$name}} = $name
4638
}
4639
}
4640
4641
my %msgtype_by_name = (
4642
'file_id' => +{ # begins === Common messages === section
4643
0 => +{'name' => 'type', 'type_name' => 'file'},
4644
1 => +{'name' => 'manufacturer', 'type_name' => 'manufacturer'},
4645
4646
2 => +{
4647
'name' => 'product',
4648
4649
'switch' => +{
4650
'_by' => 'manufacturer',
4651
'garmin' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
4652
'dynastream' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
4653
'dynastream_oem' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
4654
'favero_electronics' => +{'name' => 'favero_product', 'type_name' => 'favero_product'},
4655
'tacx' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
4656
},
4657
},
4658
4659
3 => +{'name' => 'serial_number'},
4660
4 => +{'name' => 'time_created', 'type_name' => 'date_time'},
4661
5 => +{'name' => 'number'},
4662
7 => +{'name' => 'unknown7'}, # unknown UINT32
4663
8 => +{'name' => 'product_name'},
4664
},
4665
4666
'file_creator' => +{
4667
0 => +{'name' => 'software_version'},
4668
1 => +{'name' => 'hardware_version'},
4669
},
4670
4671
'timestamp_correlation' => +{
4672
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
4673
0 => +{'name' => 'fractional_timestamp', 'scale' => 32768, 'unit' => 's'},
4674
1 => +{'name' => 'system_timestamp', 'type_name' => 'date_time'},
4675
2 => +{'name' => 'fractional_system_timestamp', 'scale' => 32768, 'unit' => 's'},
4676
3 => +{'name' => 'local_timestamp', 'type_name' => 'local_date_time'},
4677
4 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
4678
5 => +{'name' => 'system_timestamp_ms', 'unit' => 'ms'},
4679
},
4680
4681
'software' => +{ # begins === Device file messages === section
4682
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4683
3 => +{'name' => 'version', 'scale' => 100},
4684
5 => +{'name' => 'part_number'},
4685
},
4686
4687
'slave_device' => +{
4688
0 => +{'name' => 'manufacturer', 'type_name' => 'manufacturer'},
4689
4690
1 => +{
4691
'name' => 'product',
4692
4693
'switch' => +{
4694
'_by' => 'manufacturer',
4695
'garmin' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
4696
'dynastream' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
4697
'dynastream_oem' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
4698
'favero_electronics' => +{'name' => 'favero_product', 'type_name' => 'favero_product'},
4699
'tacx' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
4700
},
4701
},
4702
},
4703
4704
'capabilities' => +{
4705
0 => +{'name' => 'languages'},
4706
1 => +{'name' => 'sports', 'type_name' => 'sport_bits_0'},
4707
21 => +{'name' => 'workouts_supported', 'type_name' => 'workout_capabilities'},
4708
22 => +{'name' => 'unknown22'}, # unknown ENUM
4709
23 => +{'name' => 'connectivity_supported', 'type_name' => 'connectivity_capabilities'},
4710
24 => +{'name' => 'unknown24'}, # unknown ENUM
4711
25 => +{'name' => 'unknown25'}, # unknown UINT32Z
4712
},
4713
4714
'file_capabilities' => +{
4715
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4716
0 => +{'name' => 'type', 'type_name' => 'file'},
4717
1 => +{'name' => 'flags', 'type_name' => 'file_flags'},
4718
2 => +{'name' => 'directory'},
4719
3 => +{'name' => 'max_count'},
4720
4 => +{'name' => 'max_size', 'unit' => 'bytes'},
4721
},
4722
4723
'mesg_capabilities' => +{
4724
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4725
0 => +{'name' => 'file', 'type_name' => 'file'},
4726
1 => +{'name' => 'mesg_num', 'type_name' => 'mesg_num'},
4727
2 => +{'name' => 'count_type', 'type_name' => 'mesg_count'},
4728
4729
3 => +{
4730
'name' => 'count',
4731
4732
'switch' => +{
4733
'_by' => 'count_type',
4734
'num_per_file' => +{'name' => 'num_per_file'},
4735
'max_per_file' => +{'name' => 'max_per_file'},
4736
'max_per_file_type' => +{'name' => 'max_per_file_type'},
4737
},
4738
},
4739
},
4740
4741
'field_capabilities' => +{
4742
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4743
0 => +{'name' => 'file', 'type_name' => 'file'},
4744
1 => +{'name' => 'mesg_num', 'type_name' => 'mesg_num'},
4745
2 => +{'name' => 'field_num'},
4746
3 => +{'name' => 'count'},
4747
4 => +{'name' => 'bits'}, # not present? PATJOL: I don't see this one in the profile
4748
},
4749
4750
'device_settings' => +{ # begins === Settings file messages === section
4751
0 => +{'name' => 'active_time_zone'},
4752
1 => +{'name' => 'utc_offset'},
4753
2 => +{'name' => 'time_offset', 'unit' => 's'},
4754
3 => +{'name' => 'unknown3'}, # unknown ENUM
4755
4 => +{'name' => 'time_mode', 'type_name' => 'time_mode'},
4756
5 => +{'name' => 'time_zone_offset', 'scale' => 4, 'unit' => 'hr'},
4757
10 => +{'name' => 'unknown10'}, # unknown ENUM
4758
11 => +{'name' => 'unknown11'}, # unknown ENUM
4759
12 => +{'name' => 'backlight_mode', 'type_name' => 'backlight_mode'},
4760
13 => +{'name' => 'unknown13'}, # unknown UINT8
4761
14 => +{'name' => 'unknown14'}, # unknown UINT8
4762
15 => +{'name' => 'unknown15'}, # unknown UINT8
4763
16 => +{'name' => 'unknown16'}, # unknown ENUM
4764
17 => +{'name' => 'unknown17'}, # unknown ENUM
4765
18 => +{'name' => 'unknown18'}, # unknown ENUM
4766
21 => +{'name' => 'unknown21'}, # unknown ENUM
4767
22 => +{'name' => 'unknown22'}, # unknown ENUM
4768
26 => +{'name' => 'unknown26'}, # unknown ENUM
4769
27 => +{'name' => 'unknown27'}, # unknown ENUM
4770
29 => +{'name' => 'unknown29'}, # unknown ENUM
4771
33 => +{'name' => 'unknown33'}, # unknown UNIT8
4772
36 => +{'name' => 'activity_tracker_enabled', 'type_name' => 'bool'},
4773
38 => +{'name' => 'unknown38'}, # unknown ENUM
4774
39 => +{'name' => 'clock_time', 'type_name' => 'date_time'},
4775
40 => +{'name' => 'pages_enabled'},
4776
41 => +{'name' => 'unknown41'}, # unknown ENUM
4777
46 => +{'name' => 'move_alert_enabled', 'type_name' => 'bool'},
4778
47 => +{'name' => 'date_mode', 'type_name' => 'date_mode'},
4779
48 => +{'name' => 'unknown48'}, # unknown ENUM
4780
49 => +{'name' => 'unknown49'}, # unknown UINT16
4781
52 => +{'name' => 'unknown52'}, # unknown ENUM
4782
53 => +{'name' => 'unknown53'}, # unknown ENUM
4783
54 => +{'name' => 'unknown54'}, # unknown ENUM
4784
55 => +{'name' => 'display_orientation', 'type_name' => 'display_orientation'},
4785
56 => +{'name' => 'mounting_side', 'type_name' => 'side'},
4786
57 => +{'name' => 'default_page'},
4787
58 => +{'name' => 'autosync_min_steps', 'unit' => 'steps'},
4788
59 => +{'name' => 'autosync_min_time', 'unit' => 'minutes'},
4789
75 => +{'name' => 'unknown75'}, # unknown ENUM
4790
80 => +{'name' => 'lactate_threshold_autodetect_enabled', 'type_name' => 'bool'},
4791
85 => +{'name' => 'unknown85'}, # unknown ENUM
4792
86 => +{'name' => 'ble_auto_upload_enabled', 'type_name' => 'bool'},
4793
89 => +{'name' => 'auto_sync_frequency', 'type_name' => 'auto_sync_frequency'},
4794
90 => +{'name' => 'auto_activity_detect', 'type_name' => 'auto_activity_detect'},
4795
94 => +{'name' => 'number_of_screens'},
4796
95 => +{'name' => 'smart_notification_display_orientation', 'type_name' => 'display_orientation'},
4797
97 => +{'name' => 'unknown97'}, # unknown UINT8Z
4798
98 => +{'name' => 'unknown98'}, # unknown ENUM
4799
103 => +{'name' => 'unknown103'}, # unknown ENUM
4800
134 => +{'name' => 'tap_interface', 'type_name' => 'switch'},
4801
174 => +{'name' => 'tap_sensitivity', 'type_name' => 'tap_sensitivity'},
4802
},
4803
4804
'user_profile' => +{
4805
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4806
0 => +{'name' => 'friendly_name'}, # Used for Morning Report greeting
4807
1 => +{'name' => 'gender', 'type_name' => 'gender'},
4808
2 => +{'name' => 'age', 'unit' => 'years'},
4809
3 => +{'name' => 'height', scale => 100, 'unit' => 'm'},
4810
4 => +{'name' => 'weight', scale => 10, 'unit' => 'kg'},
4811
5 => +{'name' => 'language', 'type_name' => 'language'},
4812
6 => +{'name' => 'elev_setting', 'type_name' => 'display_measure'},
4813
7 => +{'name' => 'weight_setting', 'type_name' => 'display_measure'},
4814
8 => +{'name' => 'resting_heart_rate', 'unit' => 'bpm'},
4815
9 => +{'name' => 'default_max_running_heart_rate', 'unit' => 'bpm'},
4816
10 => +{'name' => 'default_max_biking_heart_rate', 'unit' => 'bpm'},
4817
11 => +{'name' => 'default_max_heart_rate', 'unit' => 'bpm'},
4818
12 => +{'name' => 'hr_setting', 'type_name' => 'display_heart'},
4819
13 => +{'name' => 'speed_setting', 'type_name' => 'display_measure'},
4820
14 => +{'name' => 'dist_setting', 'type_name' => 'display_measure'},
4821
16 => +{'name' => 'power_setting', 'type_name' => 'display_power'},
4822
17 => +{'name' => 'activity_class', 'type_name' => 'activity_class'},
4823
18 => +{'name' => 'position_setting', 'type_name' => 'display_position'},
4824
21 => +{'name' => 'temperature_setting', 'type_name' => 'display_measure'},
4825
22 => +{'name' => 'local_id', 'type_name' => 'user_local_id'},
4826
23 => +{'name' => 'global_id'},
4827
24 => +{'name' => 'unknown24'}, # unknown UINT8
4828
28 => +{'name' => 'wake_time', 'type_name' => 'localtime_into_day'},
4829
29 => +{'name' => 'sleep_time', 'type_name' => 'localtime_into_day'},
4830
30 => +{'name' => 'height_setting', 'type_name' => 'display_measure'},
4831
31 => +{'name' => 'user_running_step_length', scale => 1000, 'unit' => 'm'},
4832
32 => +{'name' => 'user_walking_step_length', scale => 1000, 'unit' => 'm'},
4833
33 => +{'name' => 'unknown33'}, # unknown UINT16
4834
34 => +{'name' => 'unknown34'}, # unknown UINT16
4835
35 => +{'name' => 'unknown35'}, # unknown UINT32
4836
36 => +{'name' => 'unknown36'}, # unknown UINT8
4837
38 => +{'name' => 'unknown38'}, # unknown UINT16
4838
40 => +{'name' => 'unknown40'}, # unknown FLOAT32
4839
42 => +{'name' => 'unknown42'}, # unknown UINT32
4840
47 => +{'name' => 'depth_setting', 'type_name' => 'display_measure'},
4841
49 => +{'name' => 'dive_count'},
4842
},
4843
4844
'hrm_profile' => +{
4845
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4846
0 => +{'name' => 'enabled', 'type_name' => 'bool'},
4847
1 => +{'name' => 'hrm_ant_id'},
4848
2 => +{'name' => 'log_hrv', 'type_name' => 'bool'},
4849
3 => +{'name' => 'hrm_ant_id_trans_type'},
4850
},
4851
4852
'sdm_profile' => +{
4853
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4854
0 => +{'name' => 'enabled', 'type_name' => 'bool'},
4855
1 => +{'name' => 'sdm_ant_id'},
4856
2 => +{'name' => 'sdm_cal_factor', 'scale' => 10, 'unit' => '%'},
4857
3 => +{'name' => 'odometer', 'scale' => 100, 'unit' => 'm'},
4858
4 => +{'name' => 'speed_source', 'type_name' => 'bool'},
4859
5 => +{'name' => 'sdm_ant_id_trans_type'},
4860
7 => +{'name' => 'odometer_rollover'},
4861
},
4862
4863
'bike_profile' => +{
4864
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4865
0 => +{'name' => 'name'},
4866
1 => +{'name' => 'sport', 'type_name' => 'sport'},
4867
2 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
4868
3 => +{'name' => 'odometer', 'scale' => 100, 'unit' => 'm'},
4869
4 => +{'name' => 'bike_spd_ant_id'},
4870
5 => +{'name' => 'bike_cad_ant_id'},
4871
6 => +{'name' => 'bike_spdcad_ant_id'},
4872
7 => +{'name' => 'bike_power_ant_id'},
4873
8 => +{'name' => 'custom_wheelsize', 'scale' => 1000, 'unit' => 'm'},
4874
9 => +{'name' => 'auto_wheelsize', 'scale' => 1000, 'unit' => 'm'},
4875
10 => +{'name' => 'bike_weight', 'scale' => 10, 'unit' => 'kg'},
4876
11 => +{'name' => 'power_cal_factor', 'scale' => 10, 'unit' => '%'},
4877
12 => +{'name' => 'auto_wheel_cal', 'type_name' => 'bool'},
4878
13 => +{'name' => 'auto_power_zero', 'type_name' => 'bool'},
4879
14 => +{'name' => 'id'},
4880
15 => +{'name' => 'spd_enabled', 'type_name' => 'bool'},
4881
16 => +{'name' => 'cad_enabled', 'type_name' => 'bool'},
4882
17 => +{'name' => 'spdcad_enabled', 'type_name' => 'bool'},
4883
18 => +{'name' => 'power_enabled', 'type_name' => 'bool'},
4884
19 => +{'name' => 'crank_length', 'scale' => 2, 'offset' => -110, 'unit' => 'mm'},
4885
20 => +{'name' => 'enabled', 'type_name' => 'bool'},
4886
21 => +{'name' => 'bike_spd_ant_id_trans_type'},
4887
22 => +{'name' => 'bike_cad_ant_id_trans_type'},
4888
23 => +{'name' => 'bike_spdcad_ant_id_trans_type'},
4889
24 => +{'name' => 'bike_power_ant_id_trans_type'},
4890
35 => +{'name' => 'unknown35'}, # unknown UINT8 (array[3])
4891
36 => +{'name' => 'unknown36'}, # unknown ENUM
4892
37 => +{'name' => 'odometer_rollover'},
4893
38 => +{'name' => 'front_gear_num'},
4894
39 => +{'name' => 'front_gear'},
4895
40 => +{'name' => 'rear_gear_num'},
4896
41 => +{'name' => 'rear_gear'},
4897
44 => +{'name' => 'shimano_di2_enabled'},
4898
},
4899
4900
'connectivity' => +{
4901
0 => +{'name' => 'bluetooth_enabled', 'type_name' => 'bool'},
4902
1 => +{'name' => 'bluetooth_le_enabled', 'type_name' => 'bool'},
4903
2 => +{'name' => 'ant_enabled', 'type_name' => 'bool'},
4904
3 => +{'name' => 'name'},
4905
4 => +{'name' => 'live_tracking_enabled', 'type_name' => 'bool'},
4906
5 => +{'name' => 'weather_conditions_enabled', 'type_name' => 'bool'},
4907
6 => +{'name' => 'weather_alerts_enabled', 'type_name' => 'bool'},
4908
7 => +{'name' => 'auto_activity_upload_enabled', 'type_name' => 'bool'},
4909
8 => +{'name' => 'course_download_enabled', 'type_name' => 'bool'},
4910
9 => +{'name' => 'workout_download_enabled', 'type_name' => 'bool'},
4911
10 => +{'name' => 'gps_ephemeris_download_enabled', 'type_name' => 'bool'},
4912
11 => +{'name' => 'incident_detection_enabled', 'type_name' => 'bool'},
4913
12 => +{'name' => 'grouptrack_enabled', 'type_name' => 'bool'},
4914
},
4915
4916
'watchface_settings' => +{
4917
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4918
0 => +{'name' => 'mode', 'type_name' => 'watchface_mode'},
4919
4920
1 => +{
4921
'name' => 'layout',
4922
4923
'switch' => +{
4924
'_by' => 'mode',
4925
'digital' => +{'name' => 'digital_layout', 'type_name' => 'digital_watchface_layout'},
4926
'analog' => +{'name' => 'analog_layout', 'type_name' => 'analog_watchface_layout'},
4927
},
4928
},
4929
},
4930
4931
'ohr_settings' => +{
4932
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
4933
0 => +{'name' => 'enabled', 'type_name' => 'switch'},
4934
},
4935
4936
'time_in_zone' => +{
4937
253 => +{ 'name' => 'timestamp', 'type_name' => 'date_time' },
4938
0 => +{ 'name' => 'reference_mesg', 'type_name' => 'mesg_num' },
4939
1 => +{ 'name' => 'reference_index', 'type_name' => 'message_index' },
4940
2 => +{ 'name' => 'time_in_hr_zone', 'scale' => 1000 },
4941
3 => +{ 'name' => 'time_in_speed_zone', 'scale' => 1000 },
4942
4 => +{ 'name' => 'time_in_cadence_zone', 'scale' => 1000 },
4943
5 => +{ 'name' => 'time_in_power_zone', 'scale' => 1000 },
4944
6 => +{ 'name' => 'hr_zone_high_boundary', 'unit' => 'bpm' },
4945
7 => +{ 'name' => 'speed_zone_high_boundary', 'unit' => 'm/s', 'scale' => 1000 },
4946
8 => +{ 'name' => 'cadence_zone_high_boundary', 'unit' => 'rpm' },
4947
9 => +{ 'name' => 'power_zone_high_boundary', 'unit' => 'watts' },
4948
10 => +{ 'name' => 'hr_calc_type', 'type_name' => 'hr_zone_calc' },
4949
11 => +{ 'name' => 'max_heart_rate' },
4950
12 => +{ 'name' => 'resting_heart_rate' },
4951
13 => +{ 'name' => 'threshold_heart_rate' },
4952
14 => +{ 'name' => 'pwr_calc_type', 'type_name' => 'pwr_zone_calc' },
4953
15 => +{ 'name' => 'functional_threshold_power' },
4954
},
4955
4956
'zones_target' => +{ # begins === Sport settings file messages === section
4957
1 => +{'name' => 'max_heart_rate', 'unit' => 'bpm'},
4958
2 => +{'name' => 'threshold_heart_rate', 'unit' => 'bpm'},
4959
3 => +{'name' => 'functional_threshold_power', 'unit' => 'watts'},
4960
5 => +{'name' => 'hr_calc_type', 'type_name' => 'hr_zone_calc'},
4961
7 => +{'name' => 'pwr_calc_type', 'type_name' => 'power_zone_calc'},
4962
8 => +{'name' => 'unknown8'}, # unknown UINT16
4963
9 => +{'name' => 'unknown9'}, # unknown ENUM
4964
10 => +{'name' => 'unknown10'}, # unknown ENUM
4965
11 => +{'name' => 'unknown11'}, # unknown ENUM
4966
12 => +{'name' => 'unknown12'}, # unknown ENUM
4967
13 => +{'name' => 'unknown13'}, # unknown ENUM
4968
},
4969
4970
'sport' => +{
4971
0 => +{'name' => 'sport', 'type_name' => 'sport'},
4972
1 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
4973
3 => +{'name' => 'name'},
4974
4 => +{'name' => 'unknown4'}, # unknown UINT16
4975
5 => +{'name' => 'unknown5'}, # unknown ENUM
4976
6 => +{'name' => 'unknown6'}, # unknown ENUM
4977
7 => +{'name' => 'unknown7'}, # unknown UINT8
4978
8 => +{'name' => 'unknown8'}, # unknown UINT8
4979
9 => +{'name' => 'unknown9'}, # unknown UINT8
4980
10 => +{'name' => 'unknown10'}, # unknown UINT8 (array[3])
4981
12 => +{'name' => 'unknown12'}, # unknown UINT8
4982
},
4983
4984
'hr_zone' => +{
4985
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4986
1 => +{'name' => 'high_bpm', 'unit' => 'bpm'},
4987
2 => +{'name' => 'name'},
4988
},
4989
4990
'speed_zone' => +{
4991
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4992
0 => +{'name' => 'high_value', 'scale' => 1000, 'unit' => 'm/s'},
4993
1 => +{'name' => 'name'},
4994
},
4995
4996
'cadence_zone' => +{
4997
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4998
0 => +{'name' => 'high_value', 'unit' => 'rpm'},
4999
1 => +{'name' => 'name'},
5000
},
5001
5002
'power_zone' => +{
5003
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5004
1 => +{'name' => 'high_value', 'unit' => 'watts'},
5005
2 => +{'name' => 'name'},
5006
},
5007
5008
'met_zone' => +{
5009
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5010
1 => +{'name' => 'high_bpm', 'unit' => 'bpm'},
5011
2 => +{'name' => 'calories', 'scale' => 10, 'unit' => 'kcal/min'},
5012
3 => +{'name' => 'fat_calories', 'scale' => 10, 'unit' => 'kcal/min'},
5013
},
5014
5015
'dive_settings' => +{
5016
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5017
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5018
0 => +{'name' => 'name'},
5019
1 => +{'name' => 'model', 'type_name' => 'tissue_model_type'},
5020
2 => +{'name' => 'gf_low', 'unit' => '%'},
5021
3 => +{'name' => 'gf_high', 'unit' => '%'},
5022
4 => +{'name' => 'water_type', 'type_name' => 'water_type'},
5023
5 => +{'name' => 'water_density', 'unit' => 'kg/m^3'},
5024
6 => +{'name' => 'po2_warn', 'scale' => 100, 'unit' => '%'},
5025
7 => +{'name' => 'po2_critical', 'scale' => 100, 'unit' => '%'},
5026
8 => +{'name' => 'po2_deco', 'scale' => 100, 'unit' => '%'},
5027
9 => +{'name' => 'safety_stop_enabled', 'type_name' => 'bool'},
5028
10 => +{'name' => 'bottom_depth'},
5029
11 => +{'name' => 'bottom_time'},
5030
12 => +{'name' => 'apnea_countdown_enabled', 'type_name' => 'bool'},
5031
13 => +{'name' => 'apnea_countdown_time'},
5032
14 => +{'name' => 'backlight_mode', 'type_name' => 'dive_backlight_mode'},
5033
15 => +{'name' => 'backlight_brightness'},
5034
16 => +{'name' => 'backlight_timeout', 'type_name' => 'backlight_timeout'},
5035
17 => +{'name' => 'repeat_dive_interval', 'unit' => 's'},
5036
18 => +{'name' => 'safety_stop_time', 'unit' => 's'},
5037
19 => +{'name' => 'heart_rate_source_type', 'type_name' => 'source_type'},
5038
20 => +{
5039
'name' => 'heart_rate_source',
5040
'switch' => +{
5041
'_by' => 'heart_rate_source_type',
5042
'antplus' => +{'name' => 'heart_rate_antplus_device_type', 'type_name' => 'antplus_device_type'},
5043
'local' => +{'name' => 'heart_rate_local_device_type', 'type_name' => 'local_device_type'},
5044
},
5045
},
5046
21 => +{ 'name' => 'travel_gas', 'type_name' => 'message_index' }, # Index of travel dive_gas message
5047
22 => +{ 'name' => 'ccr_low_setpoint_switch_mode', 'type_name' => 'ccr_setpoint_switch_mode' }, # If low PO2 should be switched to automatically
5048
23 => +{ 'name' => 'ccr_low_setpoint', 'scale' => 100 }, # Target PO2 when using low setpoint
5049
24 => +{ 'name' => 'ccr_low_setpoint_depth', 'unit' => 'm', 'scale' => 1000 }, # Depth to switch to low setpoint in automatic mode
5050
25 => +{ 'name' => 'ccr_high_setpoint_switch_mode', 'type' => 'ccr_setpoint_switch_mode' }, # If high PO2 should be switched to automatically
5051
26 => +{ 'name' => 'ccr_high_setpoint', 'unit' => '%', 'scale' => 100 }, # Target PO2 when using high setpoint
5052
27 => +{ 'name' => 'ccr_high_setpoint_depth', 'unit' => 'm', 'scale' => 1000 }, # Depth to switch to high setpoint in automatic mode
5053
29 => +{ 'name' => 'gas_consumption_display', 'type_name' => 'gas_consumption_rate_type' }, # Type of gas consumption rate to display. Some values are only valid if tank volume is known.
5054
30 => +{ 'name' => 'up_key_enabled', 'type_name' => 'bool' }, # Indicates whether the up key is enabled during dives
5055
35 => +{ 'name' => 'dive_sounds', 'type_name' => 'tone' }, # Sounds and vibration enabled or disabled in-dive
5056
36 => +{ 'name' => 'last_stop_multiple', 'scale' => 10 }, # Usually 1.0/1.5/2.0 representing 3/4.5/6m or 10/15/20ft
5057
37 => +{ 'name' => 'no_fly_time_mode', 'type_name' => 'no_fly_time_mode' }, # Indicates which guidelines to use for no-fly surface interval.
5058
},
5059
5060
'dive_alarm' => +{
5061
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5062
0 => +{'name' => 'depth', 'scale' => 1000, 'unit' => 'm'},
5063
1 => +{'name' => 'time', 'unit' => 's'},
5064
2 => +{'name' => 'enabled', 'type_name' => 'bool'},
5065
3 => +{'name' => 'alarm_type', 'type_name' => 'dive_alarm_type'},
5066
4 => +{'name' => 'sound', 'type_name' => 'tone'},
5067
5 => +{'name' => 'dive_types', 'type_name' => 'sub_sport'},
5068
6 => +{ 'name' => 'id' }, # Alarm ID
5069
7 => +{ 'name' => 'popup_enabled', 'type_name' => 'bool' }, # Show a visible pop-up for this alarm
5070
8 => +{ 'name' => 'trigger_on_descent', 'type_name' => 'bool' }, # Trigger the alarm on descent
5071
9 => +{ 'name' => 'trigger_on_ascent', 'type_name' => 'bool' }, # Trigger the alarm on ascent
5072
10 => +{ 'name' => 'repeating', 'type_name' => 'bool' }, # Repeat alarm each time threshold is crossed?
5073
11 => +{ 'name' => 'speed', 'scale' => 1000 }, # Ascent/descent rate (mps) setting for speed type alarms
5074
},
5075
5076
'dive_apnea_alarm' => +{
5077
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5078
0 => +{ 'name' => 'depth', 'unit' => 'm', 'scale' => 1000 }, # Depth setting (m) for depth type alarms
5079
1 => +{ 'name' => 'time', 'unit' => 's' }, # Time setting (s) for time type alarms
5080
2 => +{ 'name' => 'enabled', 'type_name' => 'bool' }, # Enablement flag
5081
3 => +{ 'name' => 'alarm_type', 'type_name' => 'dive_alarm_type' }, # Alarm type setting
5082
4 => +{ 'name' => 'sound', 'type_name' => 'tone' }, # Tone and Vibe setting for the alarm.
5083
5 => +{ 'name' => 'dive_types', 'type_name' => 'sub_sport' }, # Dive types the alarm will trigger on
5084
6 => +{ 'name' => 'id' }, # Alarm ID
5085
7 => +{ 'name' => 'popup_enabled', 'type_name' => 'bool' }, # Show a visible pop-up for this alarm
5086
8 => +{ 'name' => 'trigger_on_descent', 'type_name' => 'bool' }, # Trigger the alarm on descent
5087
9 => +{ 'name' => 'trigger_on_ascent', 'type_name' => 'bool' }, # Trigger the alarm on ascent
5088
10 => +{ 'name' => 'repeating', 'type_name' => 'bool' }, # Repeat alarm each time threshold is crossed?
5089
11 => +{ 'name' => 'speed', 'unit' => 'mps', 'scale' => 1000 }, # Ascent/descent rate (mps) setting for speed type alarms
5090
},
5091
5092
'dive_gas' => +{
5093
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5094
0 => +{'name' => 'helium_content', 'unit' => '%'},
5095
1 => +{'name' => 'oxygen_content', 'unit' => '%'},
5096
2 => +{'name' => 'status', 'type_name' => 'dive_gas_status'},
5097
3 => +{'name' => 'mode', 'type_name' => 'dive_gas_mode'},
5098
},
5099
5100
'goal' => +{ # begins === Goals file messages === section
5101
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5102
0 => +{'name' => 'sport', 'type_name' => 'sport'},
5103
1 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
5104
2 => +{'name' => 'start_date', 'type_name' => 'date_time'},
5105
3 => +{'name' => 'end_date', 'type_name' => 'date_time'},
5106
4 => +{'name' => 'type', 'type_name' => 'goal'},
5107
5 => +{'name' => 'value'},
5108
6 => +{'name' => 'repeat', 'type_name' => 'bool'},
5109
7 => +{'name' => 'target_value'},
5110
8 => +{'name' => 'recurrence', 'type_name' => 'goal_recurrence'},
5111
9 => +{'name' => 'recurrence_value'},
5112
10 => +{'name' => 'enabled', 'type_name' => 'bool'},
5113
11 => +{'name' => 'source', 'type_name' => 'goal_source'},
5114
},
5115
5116
'activity' => +{ # begins === Activity file messages === section
5117
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5118
0 => +{'name' => 'total_timer_time', 'scale' => 1000, 'unit' => 's'},
5119
1 => +{'name' => 'num_sessions'},
5120
2 => +{'name' => 'type', 'type_name' => 'activity'},
5121
3 => +{'name' => 'event', 'type_name' => 'event'},
5122
4 => +{'name' => 'event_type', 'type_name' => 'event_type'},
5123
5 => +{'name' => 'local_timestamp', 'type_name' => 'local_date_time'},
5124
6 => +{'name' => 'event_group'},
5125
},
5126
5127
'session' => +{
5128
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5129
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5130
0 => +{'name' => 'event', 'type_name' => 'event'},
5131
1 => +{'name' => 'event_type', 'type_name' => 'event_type'},
5132
2 => +{'name' => 'start_time', 'type_name' => 'date_time'},
5133
3 => +{'name' => 'start_position_lat', 'unit' => 'semicircles'},
5134
4 => +{'name' => 'start_position_long', 'unit' => 'semicircles'},
5135
5 => +{'name' => 'sport', 'type_name' => 'sport'},
5136
6 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
5137
7 => +{'name' => 'total_elapsed_time', 'scale' => 1000, 'unit' => 's'},
5138
8 => +{'name' => 'total_timer_time', 'scale' => 1000, 'unit' => 's'},
5139
9 => +{'name' => 'total_distance', 'scale' => 100, 'unit' => 'm'},
5140
5141
10 => +{
5142
'name' => 'total_cycles', 'unit' => 'cycles',
5143
5144
'switch' => +{
5145
'_by' => 'sport',
5146
'walking' => +{'name' => 'total_steps', 'unit' => 'steps'},
5147
'running' => +{'name' => 'total_strides', 'unit' => 'strides'},
5148
'swimming' => +{'name' => 'total_strokes', 'unit' => 'strokes'},
5149
},
5150
},
5151
5152
11 => +{'name' => 'total_calories', 'unit' => 'kcal'},
5153
13 => +{'name' => 'total_fat_calories', 'unit' => 'kcal'},
5154
14 => +{'name' => 'avg_speed', 'scale' => 1000, 'unit' => 'm/s'},
5155
15 => +{'name' => 'max_speed', 'scale' => 1000, 'unit' => 'm/s'},
5156
16 => +{'name' => 'avg_heart_rate', 'unit' => 'bpm'},
5157
17 => +{'name' => 'max_heart_rate', 'unit' => 'bpm'},
5158
5159
18 => +{
5160
'name' => 'avg_cadence', 'unit' => 'rpm',
5161
5162
'switch' => +{
5163
'_by' => 'sport',
5164
'walking' => +{'name' => 'avg_walking_cadence', 'unit' => 'steps/min'},
5165
'running' => +{'name' => 'avg_running_cadence', 'unit' => 'strides/min'},
5166
'swimming' => +{'name' => 'avg_swimming_cadence', 'unit' => 'strokes/min'},
5167
},
5168
},
5169
5170
19 => +{
5171
'name' => 'max_cadence', 'unit' => 'rpm',
5172
5173
'switch' => +{
5174
'_by' => 'sport',
5175
'walking' => +{'name' => 'max_walking_cadence', 'unit' => 'steps/min'},
5176
'running' => +{'name' => 'max_running_cadence', 'unit' => 'strides/min'},
5177
'swimming' => +{'name' => 'max_swimming_cadence', 'unit' => 'strokes/min'},
5178
},
5179
},
5180
5181
20 => +{'name' => 'avg_power', 'unit' => 'watts'},
5182
21 => +{'name' => 'max_power', 'unit' => 'watts'},
5183
22 => +{'name' => 'total_ascent', 'unit' => 'm'},
5184
23 => +{'name' => 'total_descent', 'unit' => 'm'},
5185
24 => +{'name' => 'total_training_effect', 'scale' => 10},
5186
25 => +{'name' => 'first_lap_index'},
5187
26 => +{'name' => 'num_laps'},
5188
27 => +{'name' => 'event_group'},
5189
28 => +{'name' => 'trigger', 'type_name' => 'session_trigger'},
5190
29 => +{'name' => 'nec_lat', 'unit' => 'semicircles'},
5191
30 => +{'name' => 'nec_long', 'unit' => 'semicircles'},
5192
31 => +{'name' => 'swc_lat', 'unit' => 'semicircles'},
5193
32 => +{'name' => 'swc_long', 'unit' => 'semicircles'},
5194
34 => +{'name' => 'normalized_power', 'unit' => 'watts'},
5195
35 => +{'name' => 'training_stress_score', 'scale' => 10, 'unit' => 'tss'},
5196
36 => +{'name' => 'intensity_factor', 'scale' => 1000, 'unit' => 'if'},
5197
37 => +{'name' => 'left_right_balance', 'type_name' => 'left_right_balance_100'},
5198
38 => +{'name' => 'end_position_lat', 'unit' => 'semicircles'},
5199
39 => +{'name' => 'end_position_long', 'unit' => 'semicircles'},
5200
41 => +{'name' => 'avg_stroke_count', 'scale' => 10, 'unit' => 'strokes/lap'},
5201
42 => +{'name' => 'avg_stroke_distance', 'scale' => 100, 'unit' => 'm'},
5202
43 => +{'name' => 'swim_stroke', 'type_name' => 'swim_stroke'},
5203
44 => +{'name' => 'pool_length', 'scale' => 100, 'unit' => 'm'},
5204
45 => +{'name' => 'threshold_power', 'unit' => 'watts'},
5205
46 => +{'name' => 'pool_length_unit', 'type_name' => 'display_measure'},
5206
47 => +{'name' => 'num_active_lengths', 'unit' => 'lengths'},
5207
48 => +{'name' => 'total_work', 'unit' => 'J'},
5208
49 => +{'name' => 'avg_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5209
50 => +{'name' => 'max_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5210
51 => +{'name' => 'gps_accuracy', 'unit' => 'm'},
5211
52 => +{'name' => 'avg_grade', 'scale' => 100, 'unit' => '%'},
5212
53 => +{'name' => 'avg_pos_grade', 'scale' => 100, 'unit' => '%'},
5213
54 => +{'name' => 'avg_neg_grade', 'scale' => 100, 'unit' => '%'},
5214
55 => +{'name' => 'max_pos_grade', 'scale' => 100, 'unit' => '%'},
5215
56 => +{'name' => 'max_neg_grade', 'scale' => 100, 'unit' => '%'},
5216
57 => +{'name' => 'avg_temperature', 'unit' => 'deg.C'},
5217
58 => +{'name' => 'max_temperature', 'unit' => 'deg.C'},
5218
59 => +{'name' => 'total_moving_time', 'scale' => 1000, 'unit' => 's'},
5219
60 => +{'name' => 'avg_pos_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5220
61 => +{'name' => 'avg_neg_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5221
62 => +{'name' => 'max_pos_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5222
63 => +{'name' => 'max_neg_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5223
64 => +{'name' => 'min_heart_rate', 'unit' => 'bpm'},
5224
65 => +{'name' => 'time_in_hr_zone', 'scale' => 1000, 'unit' => 's'},
5225
66 => +{'name' => 'time_in_speed_zone', 'scale' => 1000, 'unit' => 's'},
5226
67 => +{'name' => 'time_in_cadence_zone', 'scale' => 1000, 'unit' => 's'},
5227
68 => +{'name' => 'time_in_power_zone', 'scale' => 1000, 'unit' => 's'},
5228
69 => +{'name' => 'avg_lap_time', 'scale' => 1000, 'unit' => 's'},
5229
70 => +{'name' => 'best_lap_index'},
5230
71 => +{'name' => 'min_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5231
78 => +{'name' => 'unknown78'}, # unknown UINT32
5232
81 => +{'name' => 'unknown81'}, # unknown ENUM
5233
82 => +{'name' => 'player_score'},
5234
83 => +{'name' => 'opponent_score'},
5235
84 => +{'name' => 'opponent_name'},
5236
85 => +{'name' => 'stroke_count', 'unit' => 'counts'},
5237
86 => +{'name' => 'zone_count', 'unit' => 'counts'},
5238
87 => +{'name' => 'max_ball_speed', 'scale' => 100, 'unit' => 'm/s'},
5239
88 => +{'name' => 'avg_ball_speed', 'scale' => 100, 'unit' => 'm/s'},
5240
89 => +{'name' => 'avg_vertical_oscillation', 'scale' => 10, 'unit' => 'mm'},
5241
90 => +{'name' => 'avg_stance_time_percent', 'scale' => 100, 'unit' => '%'},
5242
91 => +{'name' => 'avg_stance_time', 'scale' => 10, 'unit' => 'ms'},
5243
92 => +{'name' => 'avg_fractional_cadence', 'scale' => 128, 'unit' => 'rpm'},
5244
93 => +{'name' => 'max_fractional_cadence', 'scale' => 128, 'unit' => 'rpm'},
5245
94 => +{'name' => 'total_fractional_cycles', 'scale' => 128, 'unit' => 'cycles'},
5246
95 => +{'name' => 'avg_total_hemoglobin_conc', 'scale' => 100, 'unit' => 'g/dL'},
5247
96 => +{'name' => 'min_total_hemoglobin_conc', 'scale' => 100, 'unit' => 'g/dL'},
5248
97 => +{'name' => 'max_total_hemoglobin_conc', 'scale' => 100, 'unit' => 'g/dL'},
5249
98 => +{'name' => 'avg_saturated_hemoglobin_percent', 'scale' => 10, 'unit' => '%'},
5250
99 => +{'name' => 'min_saturated_hemoglobin_percent', 'scale' => 10, 'unit' => '%'},
5251
100 => +{'name' => 'max_saturated_hemoglobin_percent', 'scale' => 10, 'unit' => '%'},
5252
101 => +{'name' => 'avg_left_torque_effectiveness', 'scale' => 2, 'unit' => '%'},
5253
102 => +{'name' => 'avg_right_torque_effectiveness', 'scale' => 2, 'unit' => '%'},
5254
103 => +{'name' => 'avg_left_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5255
104 => +{'name' => 'avg_right_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5256
105 => +{'name' => 'avg_combined_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5257
106 => +{'name' => 'unknown106'}, # unknown UINT16
5258
107 => +{'name' => 'unknown107'}, # unknown UINT16
5259
108 => +{'name' => 'unknown108'}, # unknown UINT16
5260
109 => +{'name' => 'unknown109'}, # unknown UINT8
5261
110 => +{'name' => 'sport_profile_name'}, # Sport name from associated sport mesg
5262
111 => +{'name' => 'sport_index'},
5263
112 => +{'name' => 'time_standing', 'scale' => 1000, 'unit' => 's'},
5264
113 => +{'name' => 'stand_count'},
5265
114 => +{'name' => 'avg_left_pco', 'unit' => 'mm'},
5266
115 => +{'name' => 'avg_right_pco', 'unit' => 'mm'},
5267
116 => +{'name' => 'avg_left_power_phase', 'scale' => 0.7111111, 'unit' => 'degrees'},
5268
117 => +{'name' => 'avg_left_power_phase_peak', 'scale' => 0.7111111, 'unit' => 'degrees'},
5269
118 => +{'name' => 'avg_right_power_phase', 'scale' => 0.7111111, 'unit' => 'degrees'},
5270
119 => +{'name' => 'avg_right_power_phase_peak', 'scale' => 0.7111111, 'unit' => 'degrees'},
5271
120 => +{'name' => 'avg_power_position', 'unit' => 'watts'},
5272
121 => +{'name' => 'max_power_position', 'unit' => 'watts'},
5273
122 => +{'name' => 'avg_cadence_position', 'unit' => 'rpm'},
5274
123 => +{'name' => 'max_cadence_position', 'unit' => 'rpm'},
5275
124 => +{'name' => 'enhanced_avg_speed', 'scale' => 1000, 'unit' => 'm/s'},
5276
125 => +{'name' => 'enhanced_max_speed', 'scale' => 1000, 'unit' => 'm/s'},
5277
126 => +{'name' => 'enhanced_avg_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5278
127 => +{'name' => 'enhanced_min_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5279
128 => +{'name' => 'enhanced_max_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5280
129 => +{'name' => 'avg_lev_motor_power', 'unit' => 'watts'},
5281
130 => +{'name' => 'max_lev_motor_power', 'unit' => 'watts'},
5282
131 => +{'name' => 'lev_battery_consumption', 'scale' => 2, 'unit' => '%'},
5283
132 => +{'name' => 'avg_vertical_ratio', 'scale' => 100, 'unit' => '%'},
5284
133 => +{'name' => 'avg_stance_time_balance', 'scale' => 100, 'unit' => '%'},
5285
134 => +{'name' => 'avg_step_length', 'scale' => 10, 'unit' => 'mm'},
5286
137 => +{'name' => 'total_anaerobic_training_effect', 'scale' => 10},
5287
139 => +{'name' => 'avg_vam', 'scale' => 1000, 'unit' => 'm/s'},
5288
140 => +{ 'name' => 'avg_depth', 'unit' => 'm', 'scale' => 1000 }, # 0 if above water
5289
141 => +{ 'name' => 'max_depth', 'unit' => 'm', 'scale' => 1000 }, # 0 if above water
5290
142 => +{ 'name' => 'surface_interval', 'unit' => 's' }, # Time since end of last dive
5291
143 => +{ 'name' => 'start_cns', 'unit' => '%' },
5292
144 => +{ 'name' => 'end_cns', 'unit' => '%' },
5293
145 => +{ 'name' => 'start_n2', 'unit' => '%' },
5294
146 => +{ 'name' => 'end_n2', 'unit' => '%' },
5295
147 => +{ 'name' => 'avg_respiration_rate' },
5296
148 => +{ 'name' => 'max_respiration_rate' },
5297
149 => +{ 'name' => 'min_respiration_rate' },
5298
150 => +{ 'name' => 'min_temperature', 'unit' => 'deg.C' },
5299
155 => +{ 'name' => 'o2_toxicity', 'unit' => 'OTUs' },
5300
156 => +{ 'name' => 'dive_number' },
5301
168 => +{ 'name' => 'training_load_peak', 'scale' => 65536 },
5302
169 => +{ 'name' => 'enhanced_avg_respiration_rate', 'unit' => 'breaths/min', 'scale' => 100 },
5303
170 => +{ 'name' => 'enhanced_max_respiration_rate', 'unit' => 'breaths/min' },
5304
180 => +{ 'name' => 'enhanced_min_respiration_rate', 'scale' => 100 },
5305
181 => +{'name' => 'total_grit', 'unit' => 'kGrit'},
5306
182 => +{'name' => 'total_flow', 'unit' => 'Flow'},
5307
183 => +{'name' => 'jump_count'},
5308
186 => +{'name' => 'avg_grit', 'unit' => 'kGrit'},
5309
187 => +{'name' => 'avg_flow', 'unit' => 'Flow'},
5310
192 => +{'name' => 'workout_feel'}, # A 0-100 scale representing how a user felt while performing a workout. Low values are considered feeling bad, while high values are good.
5311
193 => +{'name' => 'workout_rpe'}, # Common Borg CR10 / 0-10 RPE scale, multiplied 10x.. Aggregate score for all workouts in a single session.
5312
194 => +{'name' => 'avg_spo2', 'unit' => 'percent'}, # Average SPO2 for the monitoring session
5313
195 => +{'name' => 'avg_stress', 'unit' => 'percent'}, # Average stress for the monitoring session
5314
197 => +{'name' => 'sdrr_hrv', 'unit' => 'mS'}, # Standard deviation of R-R interval (SDRR) - Heart rate variability measure most useful for wellness users.
5315
198 => +{'name' => 'rmssd_hrv', 'unit' => 'mS'}, # Root mean square successive difference (RMSSD) - Heart rate variability measure most useful for athletes
5316
199 => +{'name' => 'total_fractional_ascent', 'unit' => 'm'},
5317
200 => +{'name' => 'total_fractional_descent', 'unit' => 'm'},
5318
208 => +{'name' => 'avg_core_temperature', 'unit' => 'deg.C'},
5319
209 => +{'name' => 'min_core_temperature', 'unit' => 'deg.C'},
5320
210 => +{'name' => 'max_core_temperature', 'unit' => 'deg.C'},
5321
},
5322
5323
'lap' => +{
5324
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5325
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5326
0 => +{'name' => 'event', 'type_name' => 'event'},
5327
1 => +{'name' => 'event_type', 'type_name' => 'event_type'},
5328
2 => +{'name' => 'start_time', 'type_name' => 'date_time'},
5329
3 => +{'name' => 'start_position_lat', 'unit' => 'semicircles'},
5330
4 => +{'name' => 'start_position_long', 'unit' => 'semicircles'},
5331
5 => +{'name' => 'end_position_lat', 'unit' => 'semicircles'},
5332
6 => +{'name' => 'end_position_long', 'unit' => 'semicircles'},
5333
7 => +{'name' => 'total_elapsed_time', 'scale' => 1000, 'unit' => 's'},
5334
8 => +{'name' => 'total_timer_time', 'scale' => 1000, 'unit' => 's'},
5335
9 => +{'name' => 'total_distance', 'scale' => 100, 'unit' => 'm'},
5336
5337
10 => +{
5338
'name' => 'total_cycles', 'unit' => 'cycles',
5339
5340
'switch' => +{
5341
'_by' => 'sport',
5342
'walking' => +{'name' => 'total_steps', 'unit' => 'steps'},
5343
'running' => +{'name' => 'total_strides', 'unit' => 'strides'},
5344
'swimming' => +{'name' => 'total_strokes', 'unit' => 'strokes'},
5345
},
5346
},
5347
5348
11 => +{'name' => 'total_calories', 'unit' => 'kcal'},
5349
12 => +{'name' => 'total_fat_calories', 'unit' => 'kcal'},
5350
13 => +{'name' => 'avg_speed', 'scale' => 1000, 'unit' => 'm/s'},
5351
14 => +{'name' => 'max_speed', 'scale' => 1000, 'unit' => 'm/s'},
5352
15 => +{'name' => 'avg_heart_rate', 'unit' => 'bpm'},
5353
16 => +{'name' => 'max_heart_rate', 'unit' => 'bpm'},
5354
5355
17 => +{
5356
'name' => 'avg_cadence', 'unit' => 'rpm',
5357
5358
'switch' => +{
5359
'_by' => 'sport',
5360
'walking' => +{'name' => 'avg_walking_cadence', 'unit' => 'steps/min'},
5361
'running' => +{'name' => 'avg_running_cadence', 'unit' => 'strides/min'},
5362
'swimming' => +{'name' => 'avg_swimming_cadence', 'unit' => 'strokes/min'},
5363
},
5364
},
5365
5366
18 => +{
5367
'name' => 'max_cadence', 'unit' => 'rpm',
5368
5369
'switch' => +{
5370
'_by' => 'sport',
5371
'walking' => +{'name' => 'max_walking_cadence', 'unit' => 'steps/min'},
5372
'running' => +{'name' => 'max_running_cadence', 'unit' => 'strides/min'},
5373
'swimming' => +{'name' => 'max_swimming_cadence', 'unit' => 'strokes/min'},
5374
},
5375
},
5376
5377
19 => +{'name' => 'avg_power', 'unit' => 'watts'},
5378
20 => +{'name' => 'max_power', 'unit' => 'watts'},
5379
21 => +{'name' => 'total_ascent', 'unit' => 'm'},
5380
22 => +{'name' => 'total_descent', 'unit' => 'm'},
5381
23 => +{'name' => 'intensity', 'type_name' => 'intensity'},
5382
24 => +{'name' => 'lap_trigger', 'type_name' => 'lap_trigger'},
5383
25 => +{'name' => 'sport', 'type_name' => 'sport'},
5384
26 => +{'name' => 'event_group'},
5385
27 => +{'name' => 'nec_lat', 'unit' => 'semicircles'}, # not present?
5386
28 => +{'name' => 'nec_long', 'unit' => 'semicircles'}, # not present?
5387
29 => +{'name' => 'swc_lat', 'unit' => 'semicircles'}, # not present?
5388
30 => +{'name' => 'swc_long', 'unit' => 'semicircles'}, # not present?
5389
32 => +{'name' => 'num_lengths', 'unit' => 'lengths'},
5390
33 => +{'name' => 'normalized_power', 'unit' => 'watts'},
5391
34 => +{'name' => 'left_right_balance', 'type_name' => 'left_right_balance_100'},
5392
35 => +{'name' => 'first_length_index'},
5393
37 => +{'name' => 'avg_stroke_distance', 'scale' => 100, 'unit' => 'm'},
5394
38 => +{'name' => 'swim_stroke', 'type_name' => 'swim_stroke'},
5395
39 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
5396
40 => +{'name' => 'num_active_lengths', 'unit' => 'lengths'},
5397
41 => +{'name' => 'total_work', 'unit' => 'J'},
5398
42 => +{'name' => 'avg_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5399
43 => +{'name' => 'max_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5400
44 => +{'name' => 'gps_accuracy', 'unit' => 'm'},
5401
45 => +{'name' => 'avg_grade', 'scale' => 100, 'unit' => '%'},
5402
46 => +{'name' => 'avg_pos_grade', 'scale' => 100, 'unit' => '%'},
5403
47 => +{'name' => 'avg_neg_grade', 'scale' => 100, 'unit' => '%'},
5404
48 => +{'name' => 'max_pos_grade', 'scale' => 100, 'unit' => '%'},
5405
49 => +{'name' => 'max_neg_grade', 'scale' => 100, 'unit' => '%'},
5406
50 => +{'name' => 'avg_temperature', 'unit' => 'deg.C'},
5407
51 => +{'name' => 'max_temperature', 'unit' => 'deg.C'},
5408
52 => +{'name' => 'total_moving_time', 'scale' => 1000, 'unit' => 's'},
5409
53 => +{'name' => 'avg_pos_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5410
54 => +{'name' => 'avg_neg_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5411
55 => +{'name' => 'max_pos_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5412
56 => +{'name' => 'max_neg_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5413
57 => +{'name' => 'time_in_hr_zone', 'scale' => 1000, 'unit' => 's'},
5414
58 => +{'name' => 'time_in_speed_zone', 'scale' => 1000, 'unit' => 's'},
5415
59 => +{'name' => 'time_in_cadence_zone', 'scale' => 1000, 'unit' => 's'},
5416
60 => +{'name' => 'time_in_power_zone', 'scale' => 1000, 'unit' => 's'},
5417
61 => +{'name' => 'repetition_num'},
5418
62 => +{'name' => 'min_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5419
63 => +{'name' => 'min_heart_rate', 'unit' => 'bpm'},
5420
70 => +{'name' => 'unknown70'}, # unknown UINT32
5421
71 => +{'name' => 'wkt_step_index', 'type_name' => 'message_index'},
5422
72 => +{'name' => 'unknown72'}, # unknown ENUM
5423
74 => +{'name' => 'opponent_score'},
5424
75 => +{'name' => 'stroke_count', 'unit' => 'counts'},
5425
76 => +{'name' => 'zone_count', 'unit' => 'counts'},
5426
77 => +{'name' => 'avg_vertical_oscillation', 'scale' => 10, 'unit' => 'mm'},
5427
78 => +{'name' => 'avg_stance_time_percent', 'scale' => 100, 'unit' => '%'},
5428
79 => +{'name' => 'avg_stance_time', 'scale' => 10, 'unit' => 'ms'},
5429
80 => +{'name' => 'avg_fractional_cadence', 'scale' => 128, 'unit' => 'rpm'},
5430
81 => +{'name' => 'max_fractional_cadence', 'scale' => 128, 'unit' => 'rpm'},
5431
82 => +{'name' => 'total_fractional_cycles', 'scale' => 128, 'unit' => 'cycles'},
5432
83 => +{'name' => 'player_score'},
5433
84 => +{'name' => 'avg_total_hemoglobin_conc', 'scale' => 100, 'unit' => 'g/dL'},
5434
85 => +{'name' => 'min_total_hemoglobin_conc', 'scale' => 100, 'unit' => 'g/dL'},
5435
86 => +{'name' => 'max_total_hemoglobin_conc', 'scale' => 100, 'unit' => 'g/dL'},
5436
87 => +{'name' => 'avg_saturated_hemoglobin_percent', 'scale' => 10, 'unit' => '%'},
5437
88 => +{'name' => 'min_saturated_hemoglobin_percent', 'scale' => 10, 'unit' => '%'},
5438
89 => +{'name' => 'max_saturated_hemoglobin_percent', 'scale' => 10, 'unit' => '%'},
5439
91 => +{'name' => 'avg_left_torque_effectiveness', 'scale' => 2, 'unit' => '%'},
5440
92 => +{'name' => 'avg_right_torque_effectiveness', 'scale' => 2, 'unit' => '%'},
5441
93 => +{'name' => 'avg_left_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5442
94 => +{'name' => 'avg_right_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5443
95 => +{'name' => 'avg_combined_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5444
96 => +{'name' => 'unknown96'}, # unknown UINT16
5445
97 => +{'name' => 'unknown97'}, # unknown UINT16
5446
98 => +{'name' => 'time_standing', 'scale' => 1000, 'unit' => 's'},
5447
99 => +{'name' => 'stand_count'},
5448
100 => +{'name' => 'avg_left_pco', 'unit' => 'mm'},
5449
101 => +{'name' => 'avg_right_pco', 'unit' => 'mm'},
5450
102 => +{'name' => 'avg_left_power_phase', 'scale' => 0.7111111, 'unit' => 'degrees'},
5451
103 => +{'name' => 'avg_left_power_phase_peak', 'scale' => 0.7111111, 'unit' => 'degrees'},
5452
104 => +{'name' => 'avg_right_power_phase', 'scale' => 0.7111111, 'unit' => 'degrees'},
5453
105 => +{'name' => 'avg_right_power_phase_peak', 'scale' => 0.7111111, 'unit' => 'degrees'},
5454
106 => +{'name' => 'avg_power_position', 'unit' => 'watts'},
5455
107 => +{'name' => 'max_power_position', 'unit' => 'watts'},
5456
108 => +{'name' => 'avg_cadence_position', 'unit' => 'rpm'},
5457
109 => +{'name' => 'max_cadence_position', 'unit' => 'rpm'},
5458
110 => +{'name' => 'enhanced_avg_speed', 'scale' => 1000, 'unit' => 'm/s'},
5459
111 => +{'name' => 'enhanced_max_speed', 'scale' => 1000, 'unit' => 'm/s'},
5460
112 => +{'name' => 'enhanced_avg_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5461
113 => +{'name' => 'enhanced_min_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5462
114 => +{'name' => 'enhanced_max_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5463
115 => +{'name' => 'avg_lev_motor_power', 'unit' => 'watts'},
5464
116 => +{'name' => 'max_lev_motor_power', 'unit' => 'watts'},
5465
117 => +{'name' => 'lev_battery_consumption', 'scale' => 2, 'unit' => '%'},
5466
118 => +{'name' => 'avg_vertical_ratio', 'scale' => 100, 'unit' => '%'},
5467
119 => +{'name' => 'avg_stance_time_balance', 'scale' => 100, 'unit' => '%'},
5468
120 => +{'name' => 'avg_step_length', 'scale' => 10, 'unit' => 'mm'},
5469
121 => +{'name' => 'avg_vam', 'scale' => 1000, 'unit' => 'm/s'},
5470
122 => +{ 'name' => 'avg_depth', 'unit' => 'm', 'scale' => 1000 }, # 0 if above water
5471
123 => +{ 'name' => 'max_depth', 'unit' => 'm', 'scale' => 1000 }, # 0 if above water
5472
124 => +{ 'name' => 'min_temperature', 'unit' => 'deg.C' },
5473
136 => +{ 'name' => 'enhanced_avg_respiration_rate', 'unit' => 'breaths/min', 'scale' => 100 },
5474
137 => +{ 'name' => 'enhanced_max_respiration_rate', 'unit' => 'breaths/min', 'scale' => 100 },
5475
147 => +{ 'name' => 'avg_respiration_rate' },
5476
148 => +{ 'name' => 'max_respiration_rate' },
5477
149 => +{'name' => 'total_grit', 'unit' => 'kGrit'},
5478
150 => +{'name' => 'total_flow', 'unit' => 'Flow'},
5479
151 => +{'name' => 'jump_count'},
5480
153 => +{'name' => 'avg_grit', 'unit' => 'kGrit'},
5481
154 => +{'name' => 'avg_flow', 'unit' => 'Flow'},
5482
156 => +{'name' => 'total_fractional_ascent', 'unit' => 'm'},
5483
157 => +{'name' => 'total_fractional_descent', 'unit' => 'm'},
5484
158 => +{'name' => 'avg_core_temperature', 'unit' => 'deg.C'},
5485
159 => +{'name' => 'min_core_temperature', 'unit' => 'deg.C'},
5486
160 => +{'name' => 'max_core_temperature', 'unit' => 'deg.C'},
5487
},
5488
5489
'length' => +{
5490
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5491
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5492
0 => +{'name' => 'event', 'type_name' => 'event'},
5493
1 => +{'name' => 'event_type', 'type_name' => 'event_type'},
5494
2 => +{'name' => 'start_time', 'type_name' => 'date_time'},
5495
3 => +{'name' => 'total_elapsed_time', 'scale' => 1000, 'unit' => 's'},
5496
4 => +{'name' => 'total_timer_time', 'scale' => 1000, 'unit' => 's'},
5497
5 => +{'name' => 'total_strokes', 'unit' => 'strokes'},
5498
6 => +{'name' => 'avg_speed', 'scale' => 1000, 'unit' => 'm/s'},
5499
7 => +{'name' => 'swim_stroke', 'type_name' => 'swim_stroke'},
5500
9 => +{'name' => 'avg_swimming_cadence', 'unit' => 'strokes/min'},
5501
10 => +{'name' => 'event_group'},
5502
11 => +{'name' => 'total_calories', 'unit' => 'kcal'},
5503
12 => +{'name' => 'length_type', 'type_name' => 'length_type'},
5504
18 => +{'name' => 'player_score'},
5505
19 => +{'name' => 'opponent_score'},
5506
20 => +{'name' => 'stroke_count', 'unit' => 'counts'},
5507
21 => +{'name' => 'zone_count', 'unit' => 'counts'},
5508
22 => +{ 'name' => 'enhanced_avg_respiration_rate', 'unit' => 'breaths/min', 'scale' => 100 },
5509
23 => +{ 'name' => 'enhanced_max_respiration_rate', 'unit' => 'breaths/min', 'scale' => 100 },
5510
24 => +{ 'name' => 'avg_respiration_rate' },
5511
25 => +{ 'name' => 'max_respiration_rate' },
5512
},
5513
5514
'record' => +{
5515
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5516
0 => +{'name' => 'position_lat', 'unit' => 'semicircles'},
5517
1 => +{'name' => 'position_long', 'unit' => 'semicircles'},
5518
2 => +{'name' => 'altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5519
3 => +{'name' => 'heart_rate', 'unit' => 'bpm'},
5520
4 => +{'name' => 'cadence', 'unit' => 'rpm'},
5521
5 => +{'name' => 'distance', 'scale' => 100, 'unit' => 'm'},
5522
6 => +{'name' => 'speed', 'scale' => 1000, 'unit' => 'm/s'},
5523
7 => +{'name' => 'power', 'unit' => 'watts'},
5524
8 => +{'name' => 'compressed_speed_distance'}, # complex decoding!
5525
9 => +{'name' => 'grade', 'scale' => 100, 'unit' => '%'},
5526
10 => +{'name' => 'resistance'},
5527
11 => +{'name' => 'time_from_course', 'scale' => 1000, 'unit' => 's'},
5528
12 => +{'name' => 'cycle_length', 'scale' => 100, 'unit' => 'm'},
5529
13 => +{'name' => 'temperature', 'unit' => 'deg.C'},
5530
17 => +{'name' => 'speed_1s', 'scale' => 16, 'unit' => 'm/s'},
5531
18 => +{'name' => 'cycles', 'unit' => 'cycles'},
5532
19 => +{'name' => 'total_cycles', 'unit' => 'cycles'},
5533
28 => +{'name' => 'compressed_accumulated_power', 'unit' => 'watts'},
5534
29 => +{'name' => 'accumulated_power', 'unit' => 'watts'},
5535
30 => +{'name' => 'left_right_balance', 'type_name' => 'left_right_balance'},
5536
31 => +{'name' => 'gps_accuracy', 'unit' => 'm'},
5537
32 => +{'name' => 'vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5538
33 => +{'name' => 'calories', 'unit' => 'kcal'},
5539
39 => +{'name' => 'vertical_oscillation', 'scale' => 10, 'unit' => 'mm'},
5540
40 => +{'name' => 'stance_time_percent', 'scale' => 100, 'unit' => '%'},
5541
41 => +{'name' => 'stance_time', 'scale' => 10, 'unit' => 'ms'},
5542
42 => +{'name' => 'activity_type', 'type_name' => 'activity_type'},
5543
43 => +{'name' => 'left_torque_effectiveness', 'scale' => 2, 'unit' => '%'},
5544
44 => +{'name' => 'right_torque_effectiveness', 'scale' => 2, 'unit' => '%'},
5545
45 => +{'name' => 'left_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5546
46 => +{'name' => 'right_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5547
47 => +{'name' => 'combined_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5548
48 => +{'name' => 'time128', 'scale' => 128, 'unit' => 's'},
5549
49 => +{'name' => 'stroke_type', 'type_name' => 'stroke_type'},
5550
50 => +{'name' => 'zone'},
5551
51 => +{'name' => 'ball_speed', 'scale' => 100, 'unit' => 'm/s'},
5552
52 => +{'name' => 'cadence256', 'scale' => 256, 'unit' => 'rpm'},
5553
53 => +{'name' => 'fractional_cadence', 'scale' => 128, 'unit' => 'rpm'},
5554
54 => +{'name' => 'total_hemoglobin_conc', 'scale' => 100, 'unit' => 'g/dL'},
5555
55 => +{'name' => 'total_hemoglobin_conc_min', 'scale' => 100, 'unit' => 'g/dL'},
5556
56 => +{'name' => 'total_hemoglobin_conc_max', 'scale' => 100, 'unit' => 'g/dL'},
5557
57 => +{'name' => 'saturated_hemoglobin_percent', 'scale' => 10, 'unit' => '%'},
5558
58 => +{'name' => 'saturated_hemoglobin_percent_min', 'scale' => 10, 'unit' => '%'},
5559
59 => +{'name' => 'saturated_hemoglobin_percent_max', 'scale' => 10, 'unit' => '%'},
5560
61 => +{'name' => 'unknown61'}, # unknown UINT16
5561
62 => +{'name' => 'device_index', 'type_name' => 'device_index'},
5562
66 => +{'name' => 'unknown66'}, # unknown SINT16
5563
67 => +{'name' => 'left_pco', 'unit' => 'mm'},
5564
68 => +{'name' => 'right_pco', 'unit' => 'mm'},
5565
69 => +{'name' => 'left_power_phase', 'scale' => 0.7111111, 'unit' => 'degrees'},
5566
70 => +{'name' => 'left_power_phase_peak', 'scale' => 0.7111111, 'unit' => 'degrees'},
5567
71 => +{'name' => 'right_power_phase', 'scale' => 0.7111111, 'unit' => 'degrees'},
5568
72 => +{'name' => 'right_power_phase_peak', 'scale' => 0.7111111, 'unit' => 'degrees'},
5569
73 => +{'name' => 'enhanced_speed', 'scale' => 1000, 'unit' => 'm/s'},
5570
78 => +{'name' => 'enhanced_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5571
81 => +{'name' => 'battery_soc', 'scale' => 2, 'unit' => '%'},
5572
82 => +{'name' => 'motor_power', 'unit' => 'watts'},
5573
83 => +{'name' => 'vertical_ratio', 'scale' => 100, 'unit' => '%'},
5574
84 => +{'name' => 'stance_time_balance', 'scale' => 100, 'unit' => '%'},
5575
85 => +{'name' => 'step_length', 'scale' => 10, 'unit' => 'mm'},
5576
87 => +{'name' => 'cycle_length16', 'scale' => 100, 'unit' => 'm'}, # Supports larger cycle sizes needed for paddlesports. Max cycle size: 655.35
5577
91 => +{'name' => 'absolute_pressure', 'unit' => 'Pa'},
5578
92 => +{'name' => 'depth', 'scale' => 1000, 'unit' => 'm'},
5579
93 => +{'name' => 'next_stop_depth', 'scale' => 1000, 'unit' => 'm'},
5580
94 => +{'name' => 'next_stop_time', 'unit' => 's'},
5581
95 => +{'name' => 'time_to_surface', 'unit' => 's'},
5582
96 => +{'name' => 'ndl_time', 'unit' => 's'},
5583
97 => +{'name' => 'cns_load', 'unit' => '%'},
5584
98 => +{'name' => 'n2_load', 'unit' => '%'},
5585
99 => +{ 'name' => 'respiration_rate' },
5586
108 => +{ 'name' => 'enhanced_respiration_rate', 'unit' => 'breaths/min', 'scale' => 100 },
5587
114 => +{'name' => 'grit'},
5588
115 => +{'name' => 'flow'},
5589
116 => +{'name' => 'current_stress', 'scale' => 100}, # Current Stress value
5590
117 => +{'name' => 'ebike_travel_range', 'unit' => 'km'},
5591
118 => +{'name' => 'ebike_battery_level', 'unit' => '%'},
5592
119 => +{'name' => 'ebike_assist_mode'},
5593
120 => +{'name' => 'ebike_assist_level_percent', 'unit' => '%'},
5594
123 => +{ 'name' => 'air_time_remaining' },
5595
124 => +{ 'name' => 'pressure_sac', 'unit' => 'bar/min', 'scale' => 100 }, # Pressure-based surface air consumption
5596
125 => +{ 'name' => 'volume_sac', 'unit' => 'l/min', 'scale' => 100 }, # Volumetric surface air consumption
5597
126 => +{ 'name' => 'rmv', 'unit' => 'l/min', 'scale' => 100 }, # Respiratory minute volume
5598
127 => +{ 'name' => 'ascent_rate', 'unit' => 'm/s', 'scale' => 1000 },
5599
129 => +{ 'name' => 'po2', 'unit' => 'percent', 'scale' => 100 }, # Current partial pressure of oxygen
5600
139 => +{'name' => 'core_temperature', 'scale' => 100, 'unit' => 'deg.C'},
5601
},
5602
5603
'event' => +{
5604
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5605
0 => +{'name' => 'event', 'type_name' => 'event'},
5606
1 => +{'name' => 'event_type', 'type_name' => 'event_type'},
5607
2 => +{'name' => 'data16'}, # no switch?
5608
5609
3 => +{
5610
'name' => 'data',
5611
5612
'switch' => +{
5613
'_by' => 'event',
5614
'timer' => +{'name' => 'timer_trigger', 'type_name' => 'timer_trigger'},
5615
'course_point' => +{'name' => 'course_point_index', 'type_name' => 'message_index'},
5616
'battery' => +{'name' => 'battery_level', 'scale' => 1000, 'unit' => 'V'},
5617
'virtual_partner_pace' => +{'name' => 'virtual_partner_speed', 'scale' => 1000, 'unit' => 'm/s'},
5618
'hr_high_alert' => +{'name' => 'hr_high_alert', 'unit' => 'bpm'},
5619
'hr_low_alert' => +{'name' => 'hr_low_alert', 'unit' => 'bpm'},
5620
'speed_high_alert' => +{'name' => 'speed_high_alert', 'scale' => 1000, 'unit' => 'm/s'},
5621
'speed_low_alert' => +{'name' => 'speed_low_alert', 'scale' => 1000, 'unit' => 'm/s'},
5622
'cad_high_alert' => +{'name' => 'cad_high_alert', 'unit' => 'rpm'},
5623
'cad_low_alert' => +{'name' => 'cad_low_alert', 'unit' => 'rpm'},
5624
'power_high_alert' => +{'name' => 'power_high_alert', 'unit' => 'watts'},
5625
'power_low_alert' => +{'name' => 'power_low_alert', 'unit' => 'watts'},
5626
'time_duration_alert' => +{'name' => 'time_duration_alert', 'scale' => 1000, 'unit' => 's'},
5627
'distance_duration_alert' => +{'name' => 'distance_duration_alert', 'scale' => 100, 'unit' => 'm'},
5628
'calorie_duration_alert' => +{'name' => 'calorie_duration_alert', 'unit' => 'kcal'},
5629
# why is this key not the same as the name?
5630
'fitness_equipment' => +{'name' => 'fitness_equipment_state', 'type_name' => 'fitness_equipment_state'},
5631
'sport_point' => +{'name' => 'sport_point', 'scale' => 11}, # complex decoding!
5632
'front_gear_change' => +{'name' => 'gear_change_data', 'scale' => 1111}, # complex decoding!
5633
'rear_gear_change' => +{'name' => 'gear_change_data', 'scale' => 1111}, # complex decoding!
5634
'rider_position_change' => +{'name' => 'rider_position', 'type_name' => 'rider_position_type'},
5635
'comm_timeout' => +{'name' => 'comm_timeout', 'type_name' => 'comm_timeout_type'},
5636
'dive_alert' => +{ 'name' => 'dive_alert', 'type_name' => 'dive_alert' },
5637
'auto_activity_detect' => +{'name' => 'auto_activity_detect_duration', 'unit' => 'min'},
5638
'radar_threat_alert' => +{'name' => 'radar_threat_alert'},
5639
},
5640
},
5641
5642
4 => +{'name' => 'event_group'},
5643
7 => +{'name' => 'score'},
5644
8 => +{'name' => 'opponent_score'},
5645
9 => +{'name' => 'front_gear_num'},
5646
10 => +{'name' => 'front_gear'},
5647
11 => +{'name' => 'rear_gear_num'},
5648
12 => +{'name' => 'rear_gear'},
5649
13 => +{'name' => 'device_index', 'type_name' => 'device_index'},
5650
14 => +{'name' => 'activity_type', 'type_name' => 'activity_type'}, # Activity Type associated with an auto_activity_detect event
5651
15 => +{
5652
'name' => 'start_timestamp', # Timestamp of when the event started
5653
5654
'switch' => +{
5655
'_by' => 'event',
5656
'auto_activity_detect' => +{'name' => 'auto_activity_detect_start_timestamp', 'type_name' => 'date_time', 'unit' => 's'},
5657
},
5658
},
5659
21 => +{'name' => 'radar_threat_level_max', 'type_name' => 'radar_threat_level_type'},
5660
22 => +{'name' => 'radar_threat_count'},
5661
23 => +{'name' => 'radar_threat_avg_approach_speed', unit => 'm/s'},
5662
24 => +{'name' => 'radar_threat_max_approach_speed', unit => 'm/s'},
5663
},
5664
5665
'device_info' => +{
5666
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5667
0 => +{'name' => 'device_index', 'type_name' => 'device_index'},
5668
5669
1 => +{
5670
'name' => 'device_type',
5671
5672
'switch' => +{
5673
'_by' => 'source_type',
5674
'bluetooth_low_energy' => +{ 'name' => 'ble_device_type', 'type_name' => 'ble_device_type' },
5675
'antplus' => +{'name' => 'antplus_device_type', 'type_name' => 'antplus_device_type'},
5676
'ant' => +{'name' => 'ant_device_type'},
5677
'local' => +{'name' => 'local_device_type', 'type_name' => 'local_device_type'},
5678
},
5679
},
5680
5681
2 => +{'name' => 'manufacturer', 'type_name' => 'manufacturer'},
5682
3 => +{'name' => 'serial_number'},
5683
5684
4 => +{
5685
'name' => 'product',
5686
5687
'switch' => +{
5688
'_by' => 'manufacturer',
5689
'garmin' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
5690
'dynastream' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
5691
'dynastream_oem' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
5692
'favero_electronics' => +{'name' => 'favero_product', 'type_name' => 'favero_product'},
5693
'tacx' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
5694
},
5695
},
5696
5697
5 => +{'name' => 'software_version', 'scale' => 100},
5698
6 => +{'name' => 'hardware_version'},
5699
7 => +{'name' => 'cum_operating_time', 'unit' => 's'},
5700
8 => +{'name' => 'unknown8'}, # unknown UINT32
5701
9 => +{'name' => 'unknown9'}, # unknown UINT8
5702
10 => +{'name' => 'battery_voltage', 'scale' => 256, 'unit' => 'V'},
5703
11 => +{'name' => 'battery_status', 'type_name' => 'battery_status'},
5704
15 => +{'name' => 'unknown15'}, # unknown UINT32
5705
16 => +{'name' => 'unknown16'}, # unknown UINT32
5706
18 => +{'name' => 'sensor_position', 'type_name' => 'body_location'},
5707
19 => +{'name' => 'descriptor'},
5708
20 => +{'name' => 'ant_transmission_type'},
5709
21 => +{'name' => 'ant_device_number'},
5710
22 => +{'name' => 'ant_network', 'type_name' => 'ant_network'},
5711
24 => +{'name' => 'unknown24'}, # unknown UINT32Z
5712
25 => +{'name' => 'source_type', 'type_name' => 'source_type'},
5713
27 => +{'name' => 'product_name'},
5714
32 => +{'name' => 'battery_level', 'unit' => '%'},
5715
},
5716
5717
'device_aux_battery_info' => +{
5718
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5719
0 => +{'name' => 'device_index', 'type_name' => 'device_index'},
5720
1 => +{'name' => 'battery_voltage', 'scale' => 256, 'unit' => 'V'},
5721
2 => +{'name' => 'battery_status', 'type_name' => 'battery_status'},
5722
},
5723
5724
'training_file' => +{
5725
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5726
0 => +{'name' => 'type', 'type_name' => 'file'},
5727
1 => +{'name' => 'manufacturer', 'type_name' => 'manufacturer'},
5728
5729
2 => +{
5730
'name' => 'product',
5731
5732
'switch' => +{
5733
'_by' => 'manufacturer',
5734
'garmin' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
5735
'dynastream' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
5736
'dynastream_oem' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
5737
'favero_electronics' => +{'name' => 'favero_product', 'type_name' => 'favero_product'},
5738
'tacx' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
5739
},
5740
},
5741
5742
3 => +{'name' => 'serial_number'},
5743
4 => +{'name' => 'time_created', 'type_name' => 'date_time'},
5744
},
5745
5746
'weather_conditions' => +{
5747
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5748
0 => +{'name' => 'weather_report', 'type_name' => 'weather_report'},
5749
1 => +{'name' => 'temperature', 'unit' => 'deg.C'},
5750
2 => +{'name' => 'condition', 'type_name' => 'weather_status'},
5751
3 => +{'name' => 'wind_direction', 'unit' => 'degrees'},
5752
4 => +{'name' => 'wind_speed', 'scale' => 1000, 'unit' => 'm/s'},
5753
5 => +{'name' => 'precipitation_probability'},
5754
6 => +{'name' => 'temperature_feels_like', 'unit' => 'deg.C'},
5755
7 => +{'name' => 'relative_humidity', 'unit' => '%'},
5756
8 => +{'name' => 'location'},
5757
9 => +{'name' => 'observed_at_time', 'type_name' => 'date_time'},
5758
10 => +{'name' => 'observed_location_lat', 'unit' => 'semicircles'},
5759
11 => +{'name' => 'observed_location_long', 'unit' => 'semicircles'},
5760
12 => +{'name' => 'day_of_week', 'type_name' => 'day_of_week'},
5761
13 => +{'name' => 'high_temperature', 'unit' => 'deg.C'},
5762
14 => +{'name' => 'low_temperature', 'unit' => 'deg.C'},
5763
},
5764
5765
'weather_alert' => +{
5766
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5767
0 => +{'name' => 'report_id'},
5768
1 => +{'name' => 'issue_time', 'type_name' => 'date_time'},
5769
2 => +{'name' => 'expire_time', 'type_name' => 'date_time'},
5770
3 => +{'name' => 'severity', 'type_name' => 'weather_severity'},
5771
4 => +{'name' => 'type', 'type_name' => 'weather_severe_type'},
5772
},
5773
5774
'gps_metadata' => +{
5775
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5776
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5777
1 => +{'name' => 'position_lat', 'unit' => 'semicircles'},
5778
2 => +{'name' => 'position_long', 'unit' => 'semicircles'},
5779
3 => +{'name' => 'enhanced_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5780
4 => +{'name' => 'enhanced_speed', 'scale' => 1000, 'unit' => 'm/s'},
5781
5 => +{'name' => 'heading', 'scale' => 100, 'unit' => 'degrees'},
5782
6 => +{'name' => 'utc_timestamp', 'type_name' => 'date_time'},
5783
7 => +{'name' => 'velocity', 'scale' => 100, 'unit' => 'm/s'},
5784
},
5785
5786
'camera_event' => +{
5787
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5788
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5789
1 => +{'name' => 'camera_event_type', 'type_name' => 'camera_event_type'},
5790
2 => +{'name' => 'camera_file_uuid'},
5791
3 => +{'name' => 'camera_orientation', 'type_name' => 'camera_orientation_type'},
5792
},
5793
5794
'gyroscope_data' => +{
5795
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5796
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5797
1 => +{'name' => 'sample_time_offset', 'unit' => 'ms'},
5798
2 => +{'name' => 'gyro_x', 'unit' => 'counts'},
5799
3 => +{'name' => 'gyro_y', 'unit' => 'counts'},
5800
4 => +{'name' => 'gyro_z', 'unit' => 'counts'},
5801
5 => +{'name' => 'calibrated_gyro_x', 'unit' => 'deg/s'},
5802
6 => +{'name' => 'calibrated_gyro_y', 'unit' => 'deg/s'},
5803
7 => +{'name' => 'calibrated_gyro_z', 'unit' => 'deg/s'},
5804
},
5805
5806
'accelerometer_data' => +{
5807
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5808
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5809
1 => +{'name' => 'sample_time_offset', 'unit' => 'ms'},
5810
2 => +{'name' => 'accel_x', 'unit' => 'counts'},
5811
3 => +{'name' => 'accel_y', 'unit' => 'counts'},
5812
4 => +{'name' => 'accel_z', 'unit' => 'counts'},
5813
5 => +{'name' => 'calibrated_accel_x', 'unit' => 'g'},
5814
6 => +{'name' => 'calibrated_accel_y', 'unit' => 'g'},
5815
7 => +{'name' => 'calibrated_accel_z', 'unit' => 'g'},
5816
8 => +{'name' => 'compressed_calibrated_accel_x', 'unit' => 'mG'},
5817
9 => +{'name' => 'compressed_calibrated_accel_y', 'unit' => 'mG'},
5818
10 => +{'name' => 'compressed_calibrated_accel_z', 'unit' => 'mG'},
5819
},
5820
5821
'magnetometer_data' => +{
5822
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5823
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5824
1 => +{'name' => 'sample_time_offset', 'unit' => 'ms'},
5825
2 => +{'name' => 'mag_x', 'unit' => 'counts'},
5826
3 => +{'name' => 'mag_y', 'unit' => 'counts'},
5827
4 => +{'name' => 'mag_z', 'unit' => 'counts'},
5828
5 => +{'name' => 'calibrated_mag_x', 'unit' => 'G'},
5829
6 => +{'name' => 'calibrated_mag_y', 'unit' => 'G'},
5830
7 => +{'name' => 'calibrated_mag_z', 'unit' => 'G'},
5831
},
5832
5833
'barometer_data' => +{
5834
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5835
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5836
1 => +{'name' => 'sample_time_offset', 'unit' => 'ms'},
5837
2 => +{'name' => 'baro_pres', 'unit' => 'Pa'},
5838
},
5839
5840
'three_d_sensor_calibration' => +{
5841
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5842
0 => +{'name' => 'sensor_type', 'type_name' => 'sensor_type'},
5843
5844
1 => +{
5845
'name' => 'calibration_factor',
5846
5847
'switch' => +{
5848
'_by' => 'sensor_type',
5849
'accelerometer' => +{'name' => 'accel_cal_factor'},
5850
'gyroscope' => +{'name' => 'gyro_cal_factor'},
5851
},
5852
},
5853
5854
2 => +{'name' => 'calibration_divisor', 'unit' => 'counts'},
5855
3 => +{'name' => 'level_shift'},
5856
4 => +{'name' => 'offset_cal'},
5857
5 => +{'name' => 'orientation_matrix', 'scale' => 65535},
5858
},
5859
5860
'one_d_sensor_calibration' => +{
5861
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5862
0 => +{'name' => 'sensor_type', 'type_name' => 'sensor_type'},
5863
5864
1 => +{
5865
'name' => 'calibration_factor',
5866
5867
'switch' => +{
5868
'_by' => 'sensor_type',
5869
'barometer' => +{'name' => 'baro_cal_factor'},
5870
},
5871
},
5872
5873
2 => +{'name' => 'calibration_divisor', 'unit' => 'counts'},
5874
3 => +{'name' => 'level_shift'},
5875
4 => +{'name' => 'offset_cal'},
5876
},
5877
5878
'video_frame' => +{
5879
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5880
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5881
1 => +{'name' => 'frame_number'},
5882
},
5883
5884
'obdii_data' => +{
5885
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5886
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5887
1 => +{'name' => 'time_offset', 'unit' => 'ms'},
5888
2 => +{'name' => 'pid'},
5889
3 => +{'name' => 'raw_data'},
5890
4 => +{'name' => 'pid_data_size'},
5891
5 => +{'name' => 'system_time'},
5892
6 => +{'name' => 'start_timestamp', 'type_name' => 'date_time'},
5893
7 => +{'name' => 'start_timestamp_ms', 'unit' => 'ms'},
5894
},
5895
5896
'nmea_sentence' => +{
5897
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5898
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5899
1 => +{'name' => 'sentence'},
5900
},
5901
5902
'aviation_attitude' => +{
5903
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5904
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5905
1 => +{'name' => 'system_time', 'unit' => 'ms'},
5906
2 => +{'name' => 'pitch', 'scale' => 10430.38, 'unit' => 'radians'},
5907
3 => +{'name' => 'roll', 'scale' => 10430.38, 'unit' => 'radians'},
5908
4 => +{'name' => 'accel_lateral', 'scale' => 100, 'unit' => 'm/s^2'},
5909
5 => +{'name' => 'accel_normal', 'scale' => 100, 'unit' => 'm/s^2'},
5910
6 => +{'name' => 'turn_rate', 'scale' => 1024, 'unit' => 'radians/second'},
5911
7 => +{'name' => 'stage', 'type_name' => 'attitude_stage'},
5912
8 => +{'name' => 'attitude_stage_complete', 'unit' => '%'},
5913
9 => +{'name' => 'track', 'scale' => 10430.38, 'unit' => 'radians'},
5914
10 => +{'name' => 'validity', 'type_name' => 'attitude_validity'},
5915
},
5916
5917
'video' => +{
5918
0 => +{'name' => 'url'},
5919
1 => +{'name' => 'hosting_provider'},
5920
2 => +{'name' => 'duration', 'unit' => 'ms'},
5921
},
5922
5923
'video_title' => +{
5924
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5925
0 => +{'name' => 'message_count'},
5926
1 => +{'name' => 'text'},
5927
},
5928
5929
'video_description' => +{
5930
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5931
0 => +{'name' => 'message_count'},
5932
1 => +{'name' => 'text'},
5933
},
5934
5935
'video_clip' => +{
5936
0 => +{'name' => 'clip_number'},
5937
1 => +{'name' => 'start_timestamp', 'type_name' => 'date_time'},
5938
2 => +{'name' => 'start_timestamp_ms', 'unit' => 'ms'},
5939
3 => +{'name' => 'end_timestamp', 'type_name' => 'date_time'},
5940
4 => +{'name' => 'end_timestamp_ms', 'unit' => 'ms'},
5941
6 => +{'name' => 'clip_start', 'unit' => 'ms'},
5942
7 => +{'name' => 'clip_end', 'unit' => 'ms'},
5943
},
5944
5945
'set' => +{
5946
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5947
0 => +{'name' => 'duration', 'scale' => 1000, 'unit' => 's'},
5948
3 => +{'name' => 'repetitions'},
5949
4 => +{'name' => 'weight', 'scale' => 16, 'unit' => 'kg'},
5950
5 => +{'name' => 'set_type', 'type_name' => 'set_type'},
5951
6 => +{'name' => 'start_time', 'type_name' => 'date_time'},
5952
7 => +{'name' => 'category', 'type_name' => 'exercise_category'},
5953
8 => +{'name' => 'category_subtype'},
5954
9 => +{'name' => 'weight_display_unit', 'type_name' => 'fit_base_unit'},
5955
10 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5956
11 => +{'name' => 'wkt_step_index', 'type_name' => 'message_index'},
5957
},
5958
5959
'jump' => +{
5960
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5961
0 => +{'name' => 'distance', 'unit' => 'm'},
5962
1 => +{'name' => 'height', 'unit' => 'm'},
5963
2 => +{'name' => 'rotations'},
5964
3 => +{'name' => 'hang_time', 'unit' => 's'},
5965
4 => +{'name' => 'score'},
5966
5 => +{'name' => 'position_lat', 'unit' => 'semicircles'},
5967
6 => +{'name' => 'position_long', 'unit' => 'semicircles'},
5968
7 => +{'name' => 'speed', 'scale' => 1000, 'unit' => 'm/s'},
5969
8 => +{'name' => 'enhanced_speed', 'scale' => 1000, 'unit' => 'm/s'},
5970
},
5971
5972
'split' => +{
5973
254 => +{ 'name' => 'message_index', 'type_name' => 'message_index' },
5974
0 => +{ 'name' => 'split_type', 'type_name' => 'split_type' },
5975
1 => +{ 'name' => 'total_elapsed_time', 'unit' => 's', 'scale' => 1000 },
5976
2 => +{ 'name' => 'total_timer_time', 'unit' => 's', 'scale' => 1000 },
5977
3 => +{ 'name' => 'total_distance', 'unit' => 'm', 'scale' => 100 },
5978
4 => +{ 'name' => 'avg_speed', 'unit' => 'm/s', 'scale' => 1000 },
5979
9 => +{ 'name' => 'start_time', 'type_name' => 'date_time' },
5980
13 => +{ 'name' => 'total_ascent', 'unit' => 'm'},
5981
14 => +{ 'name' => 'total_descent', 'unit' => 'm'},
5982
21 => +{ 'name' => 'start_position_lat', 'unit' => 'semicircles'},
5983
22 => +{ 'name' => 'start_position_long', 'unit' => 'semicircles'},
5984
23 => +{ 'name' => 'end_position_lat', 'unit' => 'semicircles'},
5985
24 => +{ 'name' => 'end_position_long', 'unit' => 'semicircles'},
5986
25 => +{ 'name' => 'max_speed', 'unit' => 'm/s', 'scale' => 1000 },
5987
26 => +{ 'name' => 'avg_vert_speed', 'unit' => 'm/s', 'scale' => 1000 },
5988
27 => +{ 'name' => 'end_time', 'type_name' => 'date_time' },
5989
28 => +{ 'name' => 'total_calories', 'unit' => 'kcal'},
5990
74 => +{ 'name' => 'start_elevation', 'unit' => 'm', 'scale' => 5, 'offset' => 500 },
5991
110 => +{ 'name' => 'total_moving_time', 'unit' => 's', 'scale' => 1000 },
5992
},
5993
5994
'split_summary' => +{
5995
254 => +{ 'name' => 'message_index', 'type_name' => 'message_index' },
5996
0 => +{ 'name' => 'split_type', 'type_name' => 'split_type' },
5997
3 => +{ 'name' => 'num_splits' },
5998
4 => +{ 'name' => 'total_timer_time', 'unit' => 's', 'scale' => 1000 },
5999
5 => +{ 'name' => 'total_distance', 'unit' => 'm', 'scale' => 100 },
6000
6 => +{ 'name' => 'avg_speed', 'unit' => 'm/s', 'scale' => 1000 },
6001
7 => +{ 'name' => 'max_speed', 'unit' => 'm/s', 'scale' => 1000 },
6002
8 => +{ 'name' => 'total_ascent', 'unit' => 'm' },
6003
9 => +{ 'name' => 'total_descent', 'unit' => 'm' },
6004
10 => +{ 'name' => 'avg_heart_rate', 'unit' => 'bpm' },
6005
11 => +{ 'name' => 'max_heart_rate', 'unit' => 'bpm' },
6006
12 => +{ 'name' => 'avg_vert_speed', 'unit' => 'm/s', 'scale' => 1000 },
6007
13 => +{ 'name' => 'total_calories', 'unit' => 'kcal' },
6008
77 => +{ 'name' => 'total_moving_time', 'unit' => 's', 'scale' => 1000 },
6009
},
6010
6011
'climb_pro' => +{
6012
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6013
0 => +{'name' => 'position_lat', 'unit' => 'semicircles'},
6014
1 => +{'name' => 'position_long', 'unit' => 'semicircles'},
6015
2 => +{'name' => 'climb_pro_event', 'type_name' => 'climb_pro_event'},
6016
3 => +{'name' => 'climb_number'},
6017
4 => +{'name' => 'climb_category'},
6018
5 => +{'name' => 'current_dist', 'unit' => 'm'},
6019
},
6020
6021
'field_description' => +{
6022
0 => +{'name' => 'developer_data_index'},
6023
1 => +{'name' => 'field_definition_number'},
6024
2 => +{'name' => 'fit_base_type_id', 'type_name' => 'fit_base_type'},
6025
3 => +{'name' => 'field_name'},
6026
4 => +{'name' => 'array'},
6027
5 => +{'name' => 'components'},
6028
6 => +{'name' => 'scale'},
6029
7 => +{'name' => 'offset'},
6030
8 => +{'name' => 'units'},
6031
9 => +{'name' => 'bits'},
6032
10 => +{'name' => 'accumulate'},
6033
13 => +{'name' => 'fit_base_unit_id', 'type_name' => 'fit_base_unit'},
6034
14 => +{'name' => 'native_mesg_num', 'type_name' => 'mesg_num'},
6035
15 => +{'name' => 'native_field_num'},
6036
},
6037
6038
'developer_data_id' => +{
6039
0 => +{'name' => 'developer_id'},
6040
1 => +{'name' => 'application_id'},
6041
2 => +{'name' => 'manufacturer_id', 'type_name' => 'manufacturer'},
6042
3 => +{'name' => 'developer_data_index'},
6043
4 => +{'name' => 'application_version'},
6044
},
6045
6046
'course' => +{ # begins === Course file messages === section
6047
4 => +{'name' => 'sport', 'type_name' => 'sport'},
6048
5 => +{'name' => 'name'},
6049
6 => +{'name' => 'capabilities', 'type_name' => 'course_capabilities'},
6050
7 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
6051
},
6052
6053
'course_point' => +{
6054
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6055
1 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6056
2 => +{'name' => 'position_lat', 'unit' => 'semicircles'},
6057
3 => +{'name' => 'position_long', 'unit' => 'semicircles'},
6058
4 => +{'name' => 'distance', 'scale' => 100, 'unit' => 'm'},
6059
5 => +{'name' => 'type', 'type_name' => 'course_point'},
6060
6 => +{'name' => 'name'},
6061
8 => +{'name' => 'favorite', 'type_name' => 'bool'},
6062
},
6063
6064
'segment_id' => +{ # begins === Segment file messages === section
6065
0 => +{'name' => 'name'},
6066
1 => +{'name' => 'uuid'},
6067
2 => +{'name' => 'sport', 'type_name' => 'sport'},
6068
3 => +{'name' => 'enabled', 'type_name' => 'bool'},
6069
4 => +{'name' => 'user_profile_primary_key'},
6070
5 => +{'name' => 'device_id'},
6071
6 => +{'name' => 'default_race_leader'},
6072
7 => +{'name' => 'delete_status', 'type_name' => 'segment_delete_status'},
6073
8 => +{'name' => 'selection_type', 'type_name' => 'segment_selection_type'},
6074
},
6075
6076
'segment_leaderboard_entry' => +{
6077
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6078
0 => +{'name' => 'name'},
6079
1 => +{'name' => 'type', 'type_name' => 'segment_leaderboard_type'},
6080
2 => +{'name' => 'group_primary_key'},
6081
3 => +{'name' => 'activity_id'},
6082
4 => +{'name' => 'segment_time', 'scale' => 1000, 'unit' => 's'},
6083
5 => +{'name' => 'activity_id_string'},
6084
},
6085
6086
'segment_point' => +{
6087
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6088
1 => +{'name' => 'position_lat', 'unit' => 'semicircles'},
6089
2 => +{'name' => 'position_long', 'unit' => 'semicircles'},
6090
3 => +{'name' => 'distance', 'scale' => 100, 'unit' => 'm'},
6091
4 => +{'name' => 'altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
6092
5 => +{'name' => 'leader_time', 'scale' => 1000, 'unit' => 's'},
6093
6 => +{ 'name' => 'enhanced_altitude', 'unit' => 'm', 'scale' => 5 }, # Accumulated altitude along the segment at the described point
6094
},
6095
6096
'segment_lap' => +{
6097
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6098
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6099
0 => +{'name' => 'event', 'type_name' => 'event'},
6100
1 => +{'name' => 'event_type', 'type_name' => 'event_type'},
6101
2 => +{'name' => 'start_time', 'type_name' => 'date_time'},
6102
3 => +{'name' => 'start_position_lat', 'unit' => 'semicircles'},
6103
4 => +{'name' => 'start_position_long', 'unit' => 'semicircles'},
6104
5 => +{'name' => 'end_position_lat', 'unit' => 'semicircles'},
6105
6 => +{'name' => 'end_position_long', 'unit' => 'semicircles'},
6106
7 => +{'name' => 'total_elapsed_time', 'scale' => 1000, 'unit' => 's'},
6107
8 => +{'name' => 'total_timer_time', 'scale' => 1000, 'unit' => 's'},
6108
9 => +{'name' => 'total_distance', 'scale' => 100, 'unit' => 'm'},
6109
6110
10 => +{
6111
'name' => 'total_cycles', 'unit' => 'cycles',
6112
6113
'switch' => +{
6114
'_by' => 'sport',
6115
'walking' => +{'name' => 'total_steps', 'unit' => 'steps'},
6116
'running' => +{'name' => 'total_strides', 'unit' => 'strides'},
6117
'swimming' => +{'name' => 'total_strokes', 'unit' => 'strokes'},
6118
},
6119
},
6120
6121
11 => +{'name' => 'total_calories', 'unit' => 'kcal'},
6122
12 => +{'name' => 'total_fat_calories', 'unit' => 'kcal'},
6123
13 => +{'name' => 'avg_speed', 'scale' => 1000, 'unit' => 'm/s'},
6124
14 => +{'name' => 'max_speed', 'scale' => 1000, 'unit' => 'm/s'},
6125
15 => +{'name' => 'avg_heart_rate', 'unit' => 'bpm'},
6126
16 => +{'name' => 'max_heart_rate', 'unit' => 'bpm'},
6127
17 => +{'name' => 'avg_cadence', 'unit' => 'rpm'},
6128
18 => +{'name' => 'max_cadence', 'unit' => 'rpm'},
6129
19 => +{'name' => 'avg_power', 'unit' => 'watts'},
6130
20 => +{'name' => 'max_power', 'unit' => 'watts'},
6131
21 => +{'name' => 'total_ascent', 'unit' => 'm'},
6132
22 => +{'name' => 'total_descent', 'unit' => 'm'},
6133
23 => +{'name' => 'sport', 'type_name' => 'sport'},
6134
24 => +{'name' => 'event_group'},
6135
25 => +{'name' => 'nec_lat', 'unit' => 'semicircles'},
6136
26 => +{'name' => 'nec_long', 'unit' => 'semicircles'},
6137
27 => +{'name' => 'swc_lat', 'unit' => 'semicircles'},
6138
28 => +{'name' => 'swc_long', 'unit' => 'semicircles'},
6139
29 => +{'name' => 'name'},
6140
30 => +{'name' => 'normalized_power', 'unit' => 'watts'},
6141
31 => +{'name' => 'left_right_balance', 'type_name' => 'left_right_balance_100'},
6142
32 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
6143
33 => +{'name' => 'total_work', 'unit' => 'J'},
6144
34 => +{'name' => 'avg_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
6145
35 => +{'name' => 'max_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
6146
36 => +{'name' => 'gps_accuracy', 'unit' => 'm'},
6147
37 => +{'name' => 'avg_grade', 'scale' => 100, 'unit' => '%'},
6148
38 => +{'name' => 'avg_pos_grade', 'scale' => 100, 'unit' => '%'},
6149
39 => +{'name' => 'avg_neg_grade', 'scale' => 100, 'unit' => '%'},
6150
40 => +{'name' => 'max_pos_grade', 'scale' => 100, 'unit' => '%'},
6151
41 => +{'name' => 'max_neg_grade', 'scale' => 100, 'unit' => '%'},
6152
42 => +{'name' => 'avg_temperature', 'unit' => 'deg.C'},
6153
43 => +{'name' => 'max_temperature', 'unit' => 'deg.C'},
6154
44 => +{'name' => 'total_moving_time', 'scale' => 1000, 'unit' => 's'},
6155
45 => +{'name' => 'avg_pos_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
6156
46 => +{'name' => 'avg_neg_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
6157
47 => +{'name' => 'max_pos_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
6158
48 => +{'name' => 'max_neg_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
6159
49 => +{'name' => 'time_in_hr_zone', 'scale' => 1000, 'unit' => 's'},
6160
50 => +{'name' => 'time_in_speed_zone', 'scale' => 1000, 'unit' => 's'},
6161
51 => +{'name' => 'time_in_cadence_zone', 'scale' => 1000, 'unit' => 's'},
6162
52 => +{'name' => 'time_in_power_zone', 'scale' => 1000, 'unit' => 's'},
6163
53 => +{'name' => 'repetition_num'},
6164
54 => +{'name' => 'min_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
6165
55 => +{'name' => 'min_heart_rate', 'unit' => 'bpm'},
6166
56 => +{'name' => 'active_time', 'scale' => 1000, 'unit' => 's'},
6167
57 => +{'name' => 'wkt_step_index', 'type_name' => 'message_index'},
6168
58 => +{'name' => 'sport_event', 'type_name' => 'sport_event'},
6169
59 => +{'name' => 'avg_left_torque_effectiveness', 'scale' => 2, 'unit' => '%'},
6170
60 => +{'name' => 'avg_right_torque_effectiveness', 'scale' => 2, 'unit' => '%'},
6171
61 => +{'name' => 'avg_left_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
6172
62 => +{'name' => 'avg_right_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
6173
63 => +{'name' => 'avg_combined_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
6174
64 => +{'name' => 'status', 'type_name' => 'segment_lap_status'},
6175
65 => +{'name' => 'uuid'},
6176
66 => +{'name' => 'avg_fractional_cadence', 'scale' => 128, 'unit' => 'rpm'},
6177
67 => +{'name' => 'max_fractional_cadence', 'scale' => 128, 'unit' => 'rpm'},
6178
68 => +{'name' => 'total_fractional_cycles', 'scale' => 128, 'unit' => 'cycles'},
6179
69 => +{'name' => 'front_gear_shift_count'},
6180
70 => +{'name' => 'rear_gear_shift_count'},
6181
71 => +{'name' => 'time_standing', 'scale' => 1000, 'unit' => 's'},
6182
72 => +{'name' => 'stand_count'},
6183
73 => +{'name' => 'avg_left_pco', 'unit' => 'mm'},
6184
74 => +{'name' => 'avg_right_pco', 'unit' => 'mm'},
6185
75 => +{'name' => 'avg_left_power_phase', 'scale' => 0.7111111, 'unit' => 'degrees'},
6186
76 => +{'name' => 'avg_left_power_phase_peak', 'scale' => 0.7111111, 'unit' => 'degrees'},
6187
77 => +{'name' => 'avg_right_power_phase', 'scale' => 0.7111111, 'unit' => 'degrees'},
6188
78 => +{'name' => 'avg_right_power_phase_peak', 'scale' => 0.7111111, 'unit' => 'degrees'},
6189
79 => +{'name' => 'avg_power_position', 'unit' => 'watts'},
6190
80 => +{'name' => 'max_power_position', 'unit' => 'watts'},
6191
81 => +{'name' => 'avg_cadence_position', 'unit' => 'rpm'},
6192
82 => +{'name' => 'max_cadence_position', 'unit' => 'rpm'},
6193
83 => +{'name' => 'manufacturer', 'type_name' => 'manufacturer'},
6194
84 => +{'name' => 'total_grit', 'unit' => 'kGrit'},
6195
85 => +{'name' => 'total_flow', 'unit' => 'Flow'},
6196
86 => +{'name' => 'avg_grit', 'unit' => 'kGrit'},
6197
87 => +{'name' => 'avg_flow', 'unit' => 'Flow'},
6198
89 => +{'name' => 'total_fractional_ascent', 'unit' => 'm'},
6199
90 => +{'name' => 'total_fractional_descent', 'unit' => 'm'},
6200
91 => +{ 'name' => 'enhanced_avg_altitude', 'unit' => 'm', 'scale' => 5 },
6201
92 => +{ 'name' => 'enhanced_max_altitude', 'unit' => 'm', 'scale' => 5 },
6202
93 => +{ 'name' => 'enhanced_min_altitude', 'unit' => 'm', 'scale' => 5 },
6203
},
6204
6205
'segment_file' => +{ # begins === Segment list file messages === section
6206
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6207
1 => +{'name' => 'file_uuid'},
6208
3 => +{'name' => 'enabled', 'type_name' => 'bool'},
6209
4 => +{'name' => 'user_profile_primary_key'},
6210
7 => +{'name' => 'leader_type', 'type_name' => 'segment_leaderboard_type'},
6211
8 => +{'name' => 'leader_group_primary_key'},
6212
9 => +{'name' => 'leader_activity_id'},
6213
10 => +{'name' => 'leader_activity_id_string'},
6214
11 => +{'name' => 'default_race_leader'},
6215
},
6216
6217
'workout' => +{ # begins === Workout file messages === section
6218
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6219
4 => +{'name' => 'sport', 'type_name' => 'sport'},
6220
5 => +{'name' => 'capabilities', 'type_name' => 'workout_capabilities'},
6221
6 => +{'name' => 'num_valid_steps'},
6222
7 => +{'name' => 'protection'}, # not present?
6223
8 => +{'name' => 'wkt_name'},
6224
11 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
6225
14 => +{'name' => 'pool_length', 'scale' => 100, 'unit' => 'm'},
6226
15 => +{'name' => 'pool_length_unit', 'type_name' => 'display_measure'},
6227
},
6228
6229
'workout_session' => +{
6230
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6231
0 => +{'name' => 'sport', 'type_name' => 'sport'},
6232
1 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
6233
2 => +{'name' => 'num_valid_steps'},
6234
3 => +{'name' => 'first_step_index'},
6235
4 => +{'name' => 'pool_length', 'scale' => 100, 'unit' => 'm'},
6236
5 => +{'name' => 'pool_length_unit', 'type_name' => 'display_measure'},
6237
},
6238
6239
'workout_step' => +{
6240
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6241
0 => +{'name' => 'wkt_step_name'},
6242
1 => +{'name' => 'duration_type', 'type_name' => 'wkt_step_duration'},
6243
6244
2 => +{
6245
'name' => 'duration_value',
6246
6247
'switch' => +{
6248
'_by' => 'duration_type',
6249
'time' => +{'name' => 'duration_time', 'scale' => 1000, 'unit' => 's'},
6250
'repetition_time' => +{'name' => 'duration_time', 'scale' => 1000, 'unit' => 's'},
6251
'distance' => +{'name' => 'duration_distance', 'scale' => 100, 'unit' => 'm'},
6252
'hr_less_than' => +{'name' => 'duration_hr', 'type_name' => 'workout_hr', 'unit' => 'bpm'},
6253
'hr_greater_than' => +{'name' => 'duration_hr', 'type_name' => 'workout_hr', 'unit' => 'bpm'},
6254
'calories' => +{'name' => 'duration_calories', 'unit' => 'kcal'},
6255
'repeat_until_steps_cmplt' => +{'name' => 'duration_step'},
6256
'repeat_until_time' => +{'name' => 'duration_step'},
6257
'repeat_until_distance' => +{'name' => 'duration_step'},
6258
'repeat_until_calories' => +{'name' => 'duration_step'},
6259
'repeat_until_hr_less_than' => +{'name' => 'duration_step'},
6260
'repeat_until_hr_greater_than' => +{'name' => 'duration_step'},
6261
'repeat_until_power_less_than' => +{'name' => 'duration_step'},
6262
'repeat_until_power_greater_than' => +{'name' => 'duration_step'},
6263
'power_less_than' => +{'name' => 'duration_power', 'type_name' => 'workout_power', 'unit' => 'watts'},
6264
'power_greater_than' => +{'name' => 'duration_power', 'type_name' => 'workout_power', 'unit' => 'watts'},
6265
'reps' => +{'name' => 'duration_reps'},
6266
},
6267
},
6268
6269
3 => +{'name' => 'target_type', 'type_name' => 'wkt_step_target'},
6270
6271
4 => +{
6272
'name' => 'target_value',
6273
6274
'switch' => +{
6275
'_by' => [qw(target_type duration_type)],
6276
'speed' => +{'name' => 'target_speed_zone'},
6277
'heart_rate' => +{'name' => 'target_hr_zone'},
6278
'cadence' => +{'name' => 'target_cadence_zone'},
6279
'power' => +{'name' => 'target_power_zone'},
6280
'repeat_until_steps_cmplt' => +{'name' => 'repeat_steps'},
6281
'repeat_until_time' => +{'name' => 'repeat_time', 'scale' => 1000, 'unit' => 's'},
6282
'repeat_until_distance' => +{'name' => 'repeat_distance', 'scale' => 100, 'unit' => 'm'},
6283
'repeat_until_calories' => +{'name' => 'repeat_calories', 'unit' => 'kcal'},
6284
'repeat_until_hr_less_than' => +{'name' => 'repeat_hr', 'type_name' => 'workout_hr', 'unit' => 'bpm'},
6285
'repeat_until_hr_greater_than' => +{'name' => 'repeat_hr', 'type_name' => 'workout_hr', 'unit' => 'bpm'},
6286
'repeat_until_power_less_than' => +{'name' => 'repeat_power', 'type_name' => 'workout_power', 'unit' => 'watts'},
6287
'repeat_until_power_greater_than' => +{'name' => 'repeat_power', 'type_name' => 'workout_power', 'unit' => 'watts'},
6288
'swim_stroke' => +{'name' => 'target_stroke_type', 'type_name' => 'swim_stroke'},
6289
},
6290
},
6291
6292
5 => +{
6293
'name' => 'custom_target_value_low',
6294
6295
'switch' => +{
6296
'_by' => 'target_type',
6297
'speed' => +{'name' => 'custom_target_speed_low', 'scale' => 1000, 'unit' => 'm/s'},
6298
'heart_rate' => +{'name' => 'custom_target_heart_rate_low', 'type_name' => 'workout_hr', 'unit' => 'bpm'},
6299
'cadence' => +{'name' => 'custom_target_cadence_low', 'unit' => 'rpm'},
6300
'power' => +{'name' => 'custom_target_power_low', 'type_name' => 'workout_power', 'unit' => 'watts'},
6301
},
6302
},
6303
6304
6 => +{
6305
'name' => 'custom_target_value_high',
6306
6307
'switch' => +{
6308
'_by' => 'target_type',
6309
'speed' => +{'name' => 'custom_target_speed_high', 'scale' => 1000, 'unit' => 'm/s'},
6310
'heart_rate' => +{'name' => 'custom_target_heart_rate_high', 'type_name' => 'workout_hr', 'unit' => 'bpm'},
6311
'cadence' => +{'name' => 'custom_target_cadence_high', 'unit' => 'rpm'},
6312
'power' => +{'name' => 'custom_target_power_high', 'type_name' => 'workout_power', 'unit' => 'watts'},
6313
},
6314
},
6315
6316
7 => +{'name' => 'intensity', 'type_name' => 'intensity'},
6317
8 => +{'name' => 'notes', 'type_name' => 'string'},
6318
9 => +{'name' => 'equipment', 'type_name' => 'workout_equipment'},
6319
10 => +{'name' => 'exercise_category', 'type_name' => 'exercise_category'},
6320
11 => +{'name' => 'exercise_name'},
6321
12 => +{'name' => 'exercise_weight', 'scale' => 100, 'unit' => 'kg'},
6322
13 => +{'name' => 'weight_display_unit', 'type_name' => 'fit_base_unit'},
6323
19 => +{'name' => 'secondary_target_type', 'type_name' => 'wkt_step_target'},
6324
20 => +{
6325
'name' => 'secondary_target_value',
6326
'switch' => +{
6327
'_by' => 'secondary_target_type',
6328
'speed' => +{'name' => 'secondary_target_speed_zone'},
6329
'heart_rate' => +{'name' => 'secondary_target_hr_zone'},
6330
'cadence' => +{'name' => 'secondary_target_cadence_zone'},
6331
'power' => +{'name' => 'secondary_target_power_zone'},
6332
'swim_stroke' => +{'name' => 'secondary_target_stroke_type', 'type_name' => 'swim_stroke'},
6333
},
6334
},
6335
},
6336
6337
'exercise_title' => +{
6338
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6339
0 => +{'name' => 'exercise_category', 'type_name' => 'exercise_category'},
6340
1 => +{'name' => 'exercise_name'},
6341
2 => +{'name' => 'wkt_step_name', 'type_name' => 'string'},
6342
},
6343
6344
'schedule' => +{ # begins === Schedule file messages === section
6345
0 => +{'name' => 'manufacturer', 'type_name' => 'manufacturer'},
6346
6347
1 => +{
6348
'name' => 'product',
6349
6350
'switch' => +{
6351
'_by' => 'manufacturer',
6352
'garmin' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
6353
'dynastream' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
6354
'dynastream_oem' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
6355
'favero_electronics' => +{'name' => 'favero_product', 'type_name' => 'favero_product'},
6356
'tacx' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
6357
},
6358
},
6359
6360
2 => +{'name' => 'serial_number'},
6361
3 => +{'name' => 'time_created', 'type_name' => 'date_time'},
6362
4 => +{'name' => 'completed', 'type_name' => 'bool'},
6363
5 => +{'name' => 'type', 'type_name' => 'schedule'},
6364
6 => +{'name' => 'schedule_time', 'type_name' => 'local_date_time'},
6365
},
6366
6367
'totals' => +{ # begins === Totals file messages === section
6368
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6369
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6370
0 => +{'name' => 'timer_time', 'unit' => 's'},
6371
1 => +{'name' => 'distance', 'unit' => 'm'},
6372
2 => +{'name' => 'calories', 'unit' => 'kcal'},
6373
3 => +{'name' => 'sport', 'type_name' => 'sport'},
6374
4 => +{'name' => 'elapsed_time', 'unit' => 's'},
6375
5 => +{'name' => 'sessions'},
6376
6 => +{'name' => 'active_time', 'unit' => 's'},
6377
9 => +{'name' => 'sport_index'},
6378
10 => +{'name' => 'profile_name'}, # unknown STRING
6379
},
6380
6381
'weight_scale' => +{ # begins === Weight scale file messages === section
6382
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6383
0 => +{'name' => 'weight', 'type_name' => 'weight', 'scale' => 100, 'unit' => 'kg'},
6384
1 => +{'name' => 'percent_fat', 'scale' => 100, 'unit' => '%'},
6385
2 => +{'name' => 'percent_hydration', 'scale' => 100, 'unit' => '%'},
6386
3 => +{'name' => 'visceral_fat_mass', 'scale' => 100, 'unit' => 'kg'},
6387
4 => +{'name' => 'bone_mass', 'scale' => 100, 'unit' => 'kg'},
6388
5 => +{'name' => 'muscle_mass', 'scale' => 100, 'unit' => 'kg'},
6389
7 => +{'name' => 'basal_met', 'scale' => 4, 'unit' => 'kcal/day'},
6390
8 => +{'name' => 'physique_rating'},
6391
9 => +{'name' => 'active_met', 'scale' => 4, 'unit' => 'kcal/day'},
6392
10 => +{'name' => 'metabolic_age', 'unit' => 'years'},
6393
11 => +{'name' => 'visceral_fat_rating'},
6394
12 => +{'name' => 'user_profile_index', 'type_name' => 'message_index'},
6395
13 => +{'name' => 'bmi', 'scale' => 10, 'unit' => 'kg/m^2'},
6396
},
6397
6398
'blood_pressure' => +{ # begins === Blood pressure file messages === section
6399
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6400
0 => +{'name' => 'systolic_pressure', 'unit' => 'mmHg'},
6401
1 => +{'name' => 'diastolic_pressure', 'unit' => 'mmHg'},
6402
2 => +{'name' => 'mean_arterial_pressure', 'unit' => 'mmHg'},
6403
3 => +{'name' => 'map_3_sample_mean', 'unit' => 'mmHg'},
6404
4 => +{'name' => 'map_morning_values', 'unit' => 'mmHg'},
6405
5 => +{'name' => 'map_evening_values', 'unit' => 'mmHg'},
6406
6 => +{'name' => 'heart_rate', 'unit' => 'bpm'},
6407
7 => +{'name' => 'heart_rate_type', 'type_name' => 'hr_type'},
6408
8 => +{'name' => 'status', 'type_name' => 'bp_status'},
6409
9 => +{'name' => 'user_profile_index', 'type_name' => 'message_index'},
6410
},
6411
6412
'monitoring_info' => +{ # begins === Monitoring file messages === section
6413
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6414
0 => +{'name' => 'local_timestamp', 'type_name' => 'local_date_time'},
6415
1 => +{'name' => 'activity_type', 'type_name' => 'activity_type'},
6416
3 => +{'name' => 'cycles_to_distance', 'scale' => 5000, 'unit' => 'm/cycle'},
6417
4 => +{'name' => 'cycles_to_calories', 'scale' => 5000, 'unit' => 'kcal/cycle'},
6418
5 => +{'name' => 'resting_metabolic_rate', 'unit' => 'kcal/day'},
6419
},
6420
6421
'monitoring' => +{
6422
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6423
0 => +{'name' => 'device_index', 'type_name' => 'device_index'},
6424
1 => +{'name' => 'calories', 'unit' => 'kcal'},
6425
2 => +{'name' => 'distance', 'scale' => 100, 'unit' => 'm'},
6426
6427
3 => +{
6428
'name' => 'cycles', 'scale' => 2, 'unit' => 'cycles',
6429
6430
'switch' => +{
6431
'_by' => 'activity_type',
6432
'walking' => +{'name' => 'total_steps', 'scale' => 1, 'unit' => 'steps'},
6433
'running' => +{'name' => 'total_strides', 'scale' => 1, 'unit' => 'strides'},
6434
'cycling' => +{'name' => 'total_strokes', 'scale' => 2, 'unit' => 'strokes'},
6435
'swimming' => +{'name' => 'total_strokes', 'scale' => 2, 'unit' => 'strokes'},
6436
},
6437
},
6438
6439
4 => +{'name' => 'active_time', 'scale' => 1000, 'unit' => 's'},
6440
5 => +{'name' => 'activity_type', 'type_name' => 'activity_type'},
6441
6 => +{'name' => 'activity_subtype', 'type_name' => 'activity_subtype'},
6442
7 => +{'name' => 'activity_level', 'type_name' => 'activity_level'},
6443
8 => +{'name' => 'distance_16', 'scale' => 100, 'unit' => 'm'},
6444
9 => +{'name' => 'cycles_16', 'scale' => 2, 'unit' => 'cycles'},
6445
10 => +{'name' => 'active_time_16', 'unit' => 's'},
6446
11 => +{'name' => 'local_timestamp', 'type_name' => 'local_date_time'},
6447
12 => +{'name' => 'temperature', 'scale' => 100, 'unit' => 'deg.C'},
6448
14 => +{'name' => 'temperature_min', 'scale' => 100, 'unit' => 'deg.C'},
6449
15 => +{'name' => 'temperature_max', 'scale' => 100, 'unit' => 'deg.C'},
6450
16 => +{'name' => 'activity_time', 'unit' => 'min'},
6451
19 => +{'name' => 'active_calories', 'unit' => 'kcal'},
6452
24 => +{'name' => 'current_activity_type_intensity'}, # complex decoding!
6453
25 => +{'name' => 'timestamp_min_8', 'unit' => 'min'},
6454
26 => +{'name' => 'timestamp_16', 'unit' => 's'},
6455
27 => +{'name' => 'heart_rate', 'unit' => 'bpm'},
6456
28 => +{'name' => 'intensity', 'scale' => 10},
6457
29 => +{'name' => 'duration_min', 'unit' => 'min'},
6458
30 => +{'name' => 'duration', 'unit' => 's'},
6459
31 => +{'name' => 'ascent', 'scale' => 1000, 'unit' => 'm'},
6460
32 => +{'name' => 'descent', 'scale' => 1000, 'unit' => 'm'},
6461
33 => +{'name' => 'moderate_activity_minutes', 'unit' => 'min'},
6462
34 => +{'name' => 'vigorous_activity_minutes', 'unit' => 'min'},
6463
},
6464
6465
'monitoring_hr_data' => +{
6466
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'}, # Must align to logging interval, for example, time must be 00:00:00 for daily log.
6467
0 => +{'name' => 'resting_heart_rate', 'unit' => 'bpm'}, # 7-day rolling average
6468
1 => +{'name' => 'current_day_resting_heart_rate', 'unit' => 'bpm'}, # RHR for today only. (Feeds into 7-day average)
6469
},
6470
6471
'spo2_data' => +{
6472
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6473
0 => +{'name' => 'reading_spo2', 'unit' => 'percent'},
6474
1 => +{'name' => 'reading_confidence'},
6475
2 => +{'name' => 'mode', 'type_name' => 'spo2_measurement_type'}, # Mode when data was captured
6476
},
6477
6478
'hr' => +{
6479
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6480
0 => +{'name' => 'fractional_timestamp', 'scale' => 32768, 'unit' => 's'},
6481
1 => +{'name' => 'time256', 'scale' => 256, 'unit' => 's'},
6482
6 => +{'name' => 'filtered_bpm', 'unit' => 'bpm'},
6483
9 => +{'name' => 'event_timestamp', 'scale' => 1024, 'unit' => 's'},
6484
10 => +{'name' => 'event_timestamp_12', 'scale' => 1024, 'unit' => 's'},
6485
},
6486
6487
'stress_level' => +{
6488
0 => +{'name' => 'stress_level_value'},
6489
1 => +{'name' => 'stress_level_time', 'type_name' => 'date_time', 'unit' => 's'},
6490
},
6491
6492
'max_met_data' => +{
6493
0 => +{'name' => 'update_time', 'type_name' => 'date_time'}, # Time maxMET and vo2 were calculated
6494
2 => +{'name' => 'vo2_max', 'unit' => 'mL/kg/min'},
6495
5 => +{'name' => 'sport', 'type_name' => 'sport'},
6496
6 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
6497
8 => +{'name' => 'max_met_category', 'type_name' => 'max_met_category'},
6498
9 => +{'name' => 'calibrated_data', 'type_name' => 'bool'}, # Indicates if calibrated data was used in the calculation
6499
12 => +{'name' => 'hr_source', 'type_name' => 'max_met_heart_rate_source'}, # Indicates if the estimate was obtained using a chest strap or wrist heart rate
6500
13 => +{'name' => 'speed_source', 'type_name' => 'max_met_speed_source'}, # Indidcates if the estimate was obtained using onboard GPS or connected GPS
6501
},
6502
6503
'hsa_body_battery_data' => +{ # Body battery data used for HSA custom data logging
6504
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6505
0 => +{'name' => 'processing_interval', 'unit' => 's'}, # Processing interval length in seconds
6506
1 => +{'name' => 'level', 'unit' => 'percent'}, # Body battery level
6507
2 => +{'name' => 'charged' }, # Body battery charged value
6508
3 => +{'name' => 'uncharged' }, # Body battery uncharged value
6509
},
6510
6511
'hsa_event' => +{ # HSA events
6512
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6513
0 => +{'name' => 'event_id'}, # Event ID
6514
},
6515
6516
'hsa_accelerometer_data' => +{ # Raw accelerometer data used for HSA custom data logging
6517
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6518
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'}, # Millisecond resolution of the timestamp
6519
1 => +{'name' => 'sampling_interval', 'unit' => 'ms'}, # Sampling Interval in Milliseconds
6520
2 => +{'name' => 'accel_x', 'scale' => 1.024, 'unit' => 'mG'}, # X-Axis Measurement
6521
3 => +{'name' => 'accel_y', 'scale' => 1.024, 'unit' => 'mG'}, # Y-Axis Measurement
6522
4 => +{'name' => 'accel_z', 'scale' => 1.024, 'unit' => 'mG'}, # Z-Axis Measurement
6523
5 => +{'name' => 'timestamp_32k'}, # 32 kHz timestamp
6524
},
6525
6526
'hsa_gyroscope_data' => +{
6527
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6528
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'}, # Millisecond resolution of the timestamp
6529
1 => +{'name' => 'sampling_interval', 'unit' => '1/32768 s'}, # Sampling Interval in 32 kHz timescale
6530
2 => +{'name' => 'gyro_x', 'scale' => 28.57143, 'unit' => 'deg/s'}, # X-Axis Measurement
6531
3 => +{'name' => 'gyro_y', 'scale' => 28.57143, 'unit' => 'deg/s'}, # Y-Axis Measurement
6532
4 => +{'name' => 'gyro_z', 'scale' => 28.57143, 'unit' => 'deg/s'}, # Z-Axis Measurement
6533
5 => +{'name' => 'timestamp_32k', 'unit' => '1/32768 s'}, # 32 kHz timestamp
6534
},
6535
6536
'hsa_step_data' => +{ # User's current daily step data used for HSA custom data logging
6537
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6538
0 => +{'name' => 'processing_interval', 'unit' => 's'}, # Processing interval length in seconds
6539
1 => +{'name' => 'steps', 'unit' => 'steps'}, # Total step sum
6540
},
6541
6542
'hsa_spo2_data' => +{ # User's current SpO2 data used for HSA custom data logging
6543
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6544
0 => +{'name' => 'processing_interval', 'unit' => 's'}, # Processing interval length in seconds
6545
1 => +{'name' => 'reading_spo2', 'unit' => 'percent'}, # SpO2 Reading
6546
2 => +{'name' => 'confidence'}, # SpO2 Confidence
6547
},
6548
6549
'hsa_stress_data' => +{ # User's current stress data used for HSA custom data logging
6550
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6551
0 => +{'name' => 'processing_interval', 'unit' => 's'}, # Processing interval length in seconds
6552
1 => +{'name' => 'stress_level', 'unit' => 's'}, # Stress Level ( 0 - 100 ) -300 indicates invalid -200 indicates large motion -100 indicates off wrist
6553
},
6554
6555
'hsa_respiration_data' => +{ # User's current respiration data used for HSA custom data logging
6556
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6557
0 => +{'name' => 'processing_interval', 'unit' => 's'}, # Processing interval length in seconds
6558
1 => +{'name' => 'respiration_rate', 'scale' => 100, 'unit' => 'breaths/min'}, # Breaths * 100 /min -300 indicates invalid -200 indicates large motion -100 indicates off wrist
6559
},
6560
6561
'hsa_heart_rate_data' => +{ # User's current heart rate data used for HSA custom data logging
6562
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6563
0 => +{'name' => 'processing_interval', 'unit' => 's'}, # Processing interval length in seconds
6564
1 => +{'name' => 'status'}, # Status of measurements in buffer - 0 indicates SEARCHING 1 indicates LOCKED
6565
2 => +{'name' => 'heart_rate', 'unit' => 'bpm'}, # Beats / min
6566
},
6567
6568
'hsa_configuration_data' => +{ # Configuration data for HSA custom data logging
6569
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'}, # Encoded configuration data
6570
0 => +{'name' => 'data'},
6571
1 => +{'name' => 'data_size'}, # Size in bytes of data field
6572
},
6573
6574
'hsa_wrist_temperature_data' => +{ # Wrist temperature data used for HSA custom data logging
6575
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6576
0 => +{'name' => 'processing_interval', 'unit' => 's'}, # Processing interval length in seconds
6577
1 => +{'name' => 'value', 'scale' => 1000, 'unit' => 'degC'}, # Wrist temperature reading
6578
},
6579
6580
'memo_glob' => +{ # begins === Other messages === section
6581
250 => +{'name' => 'part_index'},
6582
0 => +{'name' => 'memo'},
6583
1 => +{'name' => 'message_number'},
6584
2 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6585
},
6586
6587
'sleep_level' => +{
6588
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6589
0 => +{'name' => 'sleep_level', 'type_name' => 'sleep_level'},
6590
},
6591
6592
'ant_channel_id' => +{
6593
0 => +{'name' => 'channel_number'},
6594
1 => +{'name' => 'device_type'},
6595
2 => +{'name' => 'device_number'},
6596
3 => +{'name' => 'transmission_type'},
6597
4 => +{'name' => 'device_index', 'type_name' => 'device_index'},
6598
},
6599
6600
'ant_rx' => +{
6601
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6602
0 => +{'name' => 'fractional_timestamp', 'scale' => 32768, 'unit' => 's'},
6603
1 => +{'name' => 'mesg_id'},
6604
2 => +{'name' => 'mesg_data'},
6605
3 => +{'name' => 'channel_number'},
6606
4 => +{'name' => 'data'},
6607
},
6608
6609
'ant_tx' => +{
6610
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6611
0 => +{'name' => 'fractional_timestamp', 'scale' => 32768, 'unit' => 's'},
6612
1 => +{'name' => 'mesg_id'},
6613
2 => +{'name' => 'mesg_data'},
6614
3 => +{'name' => 'channel_number'},
6615
4 => +{'name' => 'data'},
6616
},
6617
6618
'exd_screen_configuration' => +{
6619
0 => +{'name' => 'screen_index'},
6620
1 => +{'name' => 'field_count'},
6621
2 => +{'name' => 'layout', 'type_name' => 'exd_layout'},
6622
3 => +{'name' => 'screen_enabled', 'type_name' => 'bool'},
6623
},
6624
6625
'exd_data_field_configuration' => +{
6626
0 => +{'name' => 'screen_index'},
6627
1 => +{'name' => 'concept_field'}, # complex decoding!
6628
2 => +{'name' => 'field_id'},
6629
3 => +{'name' => 'concept_count'},
6630
4 => +{'name' => 'display_type', 'type_name' => 'exd_display_type'},
6631
5 => +{'name' => 'title'},
6632
},
6633
6634
'exd_data_concept_configuration' => +{
6635
0 => +{'name' => 'screen_index'},
6636
1 => +{'name' => 'concept_field'}, # complex decoding!
6637
2 => +{'name' => 'field_id'},
6638
3 => +{'name' => 'concept_index'},
6639
4 => +{'name' => 'data_page'},
6640
5 => +{'name' => 'concept_key'},
6641
6 => +{'name' => 'scaling'},
6642
7 => +{'name' => 'unknown7'}, # unknown UINT8
6643
8 => +{'name' => 'data_units', 'type_name' => 'exd_data_units'},
6644
9 => +{'name' => 'qualifier', 'type_name' => 'exd_qualifiers'},
6645
10 => +{'name' => 'descriptor', 'type_name' => 'exd_descriptors'},
6646
11 => +{'name' => 'is_signed', 'type_name' => 'bool'},
6647
},
6648
6649
'dive_summary' => +{
6650
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6651
0 => +{'name' => 'reference_mesg', 'type_name' => 'mesg_num'},
6652
1 => +{'name' => 'reference_index', 'type_name' => 'message_index'},
6653
2 => +{'name' => 'avg_depth', 'scale' => 1000, 'unit' => 'm'},
6654
3 => +{'name' => 'max_depth', 'scale' => 1000, 'unit' => 'm'},
6655
4 => +{'name' => 'surface_interval', 'unit' => 's'},
6656
5 => +{'name' => 'start_cns', 'unit' => '%'},
6657
6 => +{'name' => 'end_cns', 'unit' => '%'},
6658
7 => +{'name' => 'start_n2', 'unit' => '%'},
6659
8 => +{'name' => 'end_n2', 'unit' => '%'},
6660
9 => +{'name' => 'o2_toxicity'},
6661
10 => +{'name' => 'dive_number'},
6662
11 => +{'name' => 'bottom_time', 'scale' => 1000, 'unit' => 's'},
6663
12 => +{ 'name' => 'avg_pressure_sac', 'unit' => 'bar/min', 'scale' => 100 },# Average pressure-based surface air consumption
6664
13 => +{ 'name' => 'avg_volume_sac', 'unit' => 'l/min', 'scale' => 100 }, # Average volumetric surface air consumption
6665
14 => +{ 'name' => 'avg_rmv', 'unit' => 'l/min', 'scale' => 100 }, # Average respiratory minute volume
6666
15 => +{ 'name' => 'descent_time', 'unit' => 's', 'scale' => 1000 }, # Time to reach deepest level stop
6667
16 => +{ 'name' => 'ascent_time', 'unit' => 's', 'scale' => 1000 }, # Time after leaving bottom until reaching surface
6668
17 => +{ 'name' => 'avg_ascent_rate', 'unit' => 'm/s', 'scale' => 1000 }, # Average ascent rate, not including descents or stops
6669
22 => +{ 'name' => 'avg_descent_rate', 'unit' => 'm/s', 'scale' => 1000 }, # Average descent rate, not including ascents or stops
6670
23 => +{ 'name' => 'max_ascent_rate', 'unit' => 'm/s', 'scale' => 1000 }, # Maximum ascent rate
6671
24 => +{ 'name' => 'max_descent_rate', 'unit' => 'm/s', 'scale' => 1000 }, # Maximum descent rate
6672
25 => +{ 'name' => 'hang_time', 'unit' => 's', 'scale' => 1000 }, # Time spent neither ascending nor descending
6673
},
6674
6675
'aad_accel_features' => +{ # Number of acclerometer zero crossings summed over the specified time interval
6676
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6677
0 => +{'name' => 'time', 'unit' => 's'}, # Time interval length in seconds
6678
1 => +{'name' => 'energy_total'}, # Total accelerometer energy in the interval
6679
2 => +{'name' => 'zero_cross_cnt'}, # Count of zero crossings
6680
3 => +{'name' => 'instance'}, # Instance ID of zero crossing algorithm
6681
4 => +{'name' => 'time_above_threshold', 'scale' => 25, 'unit' => 's'}, # Total accelerometer time above threshold in the interval
6682
},
6683
6684
'hrv' => +{ # heart rate variability
6685
0 => +{'name' => 'time', 'scale' => 1000, 'unit' => 's'},
6686
},
6687
6688
'beat_intervals' => +{
6689
253 => +{ 'name' => 'timestamp', 'type_name' => 'date_time' },
6690
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'}, # Milliseconds past date_time
6691
1 => +{'name' => 'time', 'unit' => 'ms'}, # Array of millisecond times between beats
6692
},
6693
6694
'hrv_status_summary' => +{
6695
253 => +{ 'name' => 'timestamp', 'type_name' => 'date_time' },
6696
0 => +{'name' => 'weekly_average', 'scale' => 128, 'unit' => 'ms'}, # 5 minute RMSSD
6697
1 => +{'name' => 'last_night_average', 'scale' => 128, 'unit' => 'ms'}, # 7 day RMSSD average over sleep
6698
2 => +{'name' => 'last_night_5_min_high', 'scale' => 128, 'unit' => 'ms'}, # Last night RMSSD average over sleep
6699
3 => +{'name' => 'baseline_low_upper', 'scale' => 128, 'unit' => 'ms'}, # 5 minute high RMSSD value over sleep
6700
4 => +{'name' => 'baseline_balanced_lower', 'scale' => 128, 'unit' => 'ms'}, # 3 week baseline, upper boundary of low HRV status
6701
5 => +{'name' => 'baseline_balanced_upper', 'scale' => 128, 'unit' => 'ms'}, # 3 week baseline, lower boundary of balanced HRV status
6702
6 => +{'name' => 'hrv_status', 'type_name' => 'hrv_status'},
6703
},
6704
6705
'hrv_value' => +{
6706
253 => +{ 'name' => 'timestamp', 'type_name' => 'date_time' },
6707
0 => +{'name' => 'value', 'scale' => 128, 'unit' => 'ms'}, # 5 minute RMSSD
6708
},
6709
6710
'raw_bbi' => +{ # Raw Beat-to-Beat Interval values
6711
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6712
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'}, # ms since last overnight_raw_bbi message
6713
1 => +{'name' => 'data'}, # Complex decoding!
6714
2 => +{'name' => 'time', 'unit' => 'ms'}, # Array of millisecond times between beats
6715
3 => +{'name' => 'quality'},
6716
4 => +{'name' => 'gap'},
6717
},
6718
6719
'respiration_rate' => +{
6720
253 => +{ 'name' => 'timestamp', 'type_name' => 'date_time' },
6721
0 => +{ 'name' => 'respiration_rate', 'unit' => 'breaths/min', 'scale' => 100 }, # Breaths * 100 /min, -300 indicates invalid, -200 indicates large motion, -100 indicates off wrist
6722
},
6723
6724
'chrono_shot_session' => +{ # Specifically used for XERO products.
6725
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6726
0 => +{'name' => 'min_speed', 'scale' => 1000, 'unit' => 'm/s'},
6727
1 => +{'name' => 'max_speed', 'scale' => 1000, 'unit' => 'm/s'},
6728
2 => +{'name' => 'avg_speed', 'scale' => 1000, 'unit' => 'm/s'},
6729
3 => +{'name' => 'shot_count'},
6730
4 => +{'name' => 'projectile_type', 'type_name' => 'projectile_type'},
6731
5 => +{'name' => 'grain_weight', 'scale' => 10, 'unit' => 'gr'},
6732
},
6733
6734
'chrono_shot_data' => +{ # Specifically used for XERO products.
6735
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6736
0 => +{'name' => 'shot_speed', 'scale' => 1000, 'unit' => 'm/s'},
6737
1 => +{'name' => 'shot_num'},
6738
},
6739
6740
'tank_update' => +{
6741
253 => +{ 'name' => 'timestamp', 'type_name' => 'date_time' },
6742
0 => +{ 'name' => 'sensor', 'type_name' => 'ant_channel_id' },
6743
1 => +{ 'name' => 'pressure', 'unit' => 'bar', 'scale' => 100 },
6744
},
6745
6746
'tank_summary' => +{
6747
253 => +{ 'name' => 'timestamp', 'type_name' => 'date_time' },
6748
0 => +{ 'name' => 'sensor', 'type_name' => 'ant_channel_id' },
6749
1 => +{ 'name' => 'start_pressure', 'unit' => 'bar', 'scale' => 100 },
6750
2 => +{ 'name' => 'end_pressure', 'unit' => 'bar', 'scale' => 100 },
6751
3 => +{ 'name' => 'volume_used', 'unit' => 'l', 'scale' => 100 },
6752
},
6753
6754
'sleep_assessment' => +{
6755
0 => +{ 'name' => 'combined_awake_score' }, # Average of awake_time_score and awakenings_count_score. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID.
6756
1 => +{ 'name' => 'awake_time_score' }, # Score that evaluates the total time spent awake between sleep. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID.
6757
2 => +{ 'name' => 'awakenings_count_score' }, # Score that evaluates the number of awakenings that interrupt sleep. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID.
6758
3 => +{ 'name' => 'deep_sleep_score' }, # Score that evaluates the amount of deep sleep. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID.
6759
4 => +{ 'name' => 'sleep_duration_score' }, # Score that evaluates the quality of sleep based on sleep stages, heart-rate variability and possible awakenings during the night. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID.
6760
5 => +{ 'name' => 'light_sleep_score', }, # Score that evaluates the amount of light sleep. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID.
6761
6 => +{ 'name' => 'overall_sleep_score' }, # Total score that summarizes the overall quality of sleep, combining sleep duration and quality. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID.
6762
7 => +{ 'name' => 'sleep_quality_score' }, # Score that evaluates the quality of sleep based on sleep stages, heart-rate variability and possible awakenings during the night. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID.
6763
8 => +{ 'name' => 'sleep_recovery_score' }, # Score that evaluates stress and recovery during sleep. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID.
6764
9 => +{ 'name' => 'rem_sleep_score' }, # Score that evaluates the amount of REM sleep. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID.
6765
10 => +{ 'name' => 'sleep_restlessness_score' }, # Score that evaluates the amount of restlessness during sleep. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID.
6766
11 => +{ 'name' => 'awakenings_count' }, # The number of awakenings during sleep.
6767
14 => +{ 'name' => 'interruptions_score' }, # Score that evaluates the sleep interruptions. If valid: 0 (worst) to 100 (best). If unknown: FIT_UINT8_INVALID.
6768
15 => +{ 'name' => 'average_stress_during_sleep' }, # Excludes stress during awake periods in the sleep window
6769
},
6770
6771
'skin_temp_overnight' => +{
6772
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6773
0 => +{'name' => 'local_timestamp', 'type_name' => 'local_date_time'},
6774
1 => +{'name' => 'average_deviation'}, # The average overnight deviation from baseline temperature in degrees C
6775
2 => +{'name' => 'average_7_day_deviation'}, # The average 7 day overnight deviation from baseline temperature in degrees C
6776
4 => +{'name' => 'nightly_value'}, # Final overnight temperature value
6777
},
6778
6779
'pad' => +{
6780
0 => +{'name' => 'pad'},
6781
},
6782
6783
'source' => +{ # begins === Undocumented messages === section
6784
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6785
# device_index in device_info
6786
0 => +{'name' => 'unknown0', 'type_name' => 'device_index'}, # unknown UINT8
6787
1 => +{'name' => 'unknown1', 'type_name' => 'device_index'}, # unknown UINT8
6788
2 => +{'name' => 'unknown2', 'type_name' => 'device_index'}, # unknown UINT8
6789
3 => +{'name' => 'unknown3', 'type_name' => 'device_index'}, # unknown UINT8
6790
4 => +{'name' => 'unknown4', 'type_name' => 'device_index'}, # unknown UINT8
6791
5 => +{'name' => 'unknown5'}, # unknown ENUM
6792
6 => +{'name' => 'unknown6'}, # unknown UINT8
6793
7 => +{'name' => 'unknown7'}, # unknown UINT8
6794
8 => +{'name' => 'unknown8'}, # unknown UINT8
6795
9 => +{'name' => 'unknown9'}, # unknown UINT8
6796
},
6797
6798
'location' => +{
6799
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6800
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6801
0 => +{'name' => 'name'}, # unknown STRING
6802
1 => +{'name' => 'position_lat', 'unit' => 'semicircles'}, # unknown SINT32
6803
2 => +{'name' => 'position_long', 'unit' => 'semicircles'}, # unknown SINT32
6804
3 => +{'name' => 'unknown3'}, # unknown UINT16 (elevation?)
6805
4 => +{'name' => 'unknown4'}, # unknown UINT16
6806
5 => +{'name' => 'unknown5'}, # unknown UINT16
6807
6 => +{'name' => 'unknown6'}, # unknown STRING
6808
},
6809
6810
'battery' => +{
6811
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6812
0 => +{'name' => 'unknown0'}, # unknown UINT16 (voltage with scale?)
6813
1 => +{'name' => 'unknown1'}, # unknown SINT16
6814
2 => +{'name' => 'charge_level', 'unit' => '%'}, # unknown UINT8
6815
3 => +{'name' => 'temperature', 'unit' => 'deg.C'}, # unknown SINT8
6816
},
6817
6818
'sensor' => +{
6819
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6820
0 => +{'name' => 'unknown0'}, # unknown UINT32Z
6821
1 => +{'name' => 'unknown1'}, # unknown UINT8
6822
2 => +{'name' => 'sensor_id'}, # unknown STRING
6823
3 => +{'name' => 'unknown3'}, # unknown ENUM
6824
4 => +{'name' => 'unknown4'}, # unknown ENUM
6825
5 => +{'name' => 'unknown5'}, # unknown ENUM
6826
6 => +{'name' => 'unknown6'}, # unknown ENUM
6827
7 => +{'name' => 'unknown7'}, # unknown ENUM
6828
8 => +{'name' => 'unknown8'}, # unknown ENUM
6829
9 => +{'name' => 'unknown9'}, # unknown UINT8
6830
10 => +{'name' => 'wheel_size', 'unit' => 'mm'}, # unknown UINT16
6831
11 => +{'name' => 'unknown11'}, # unknown UINT16
6832
12 => +{'name' => 'unknown12'}, # unknown UINT8
6833
13 => +{'name' => 'unknown13'}, # unknown UINT32
6834
14 => +{'name' => 'unknown14'}, # unknown UINT8
6835
15 => +{'name' => 'unknown15'}, # unknown UINT8
6836
16 => +{'name' => 'unknown16'}, # unknown UINT8
6837
17 => +{'name' => 'unknown17'}, # unknown UINT8Z
6838
18 => +{'name' => 'unknown18'}, # unknown UINT8Z (array[4])
6839
19 => +{'name' => 'unknown19'}, # unknown UINT8Z
6840
20 => +{'name' => 'unknown20'}, # unknown UINT8Z (array[12])
6841
21 => +{'name' => 'unknown21'}, # unknown UINT16
6842
25 => +{'name' => 'unknown25'}, # unknown UINT16
6843
26 => +{'name' => 'unknown26'}, # unknown UINT16
6844
27 => +{'name' => 'unknown27'}, # unknown UINT8
6845
28 => +{'name' => 'unknown28'}, # unknown UINT8 (array[4])
6846
29 => +{'name' => 'unknown29'}, # unknown UINT8 (array[4])
6847
30 => +{'name' => 'unknown30'}, # unknown UINT8 (array[4])
6848
31 => +{'name' => 'unknown31'}, # unknown UINT8
6849
32 => +{'name' => 'unknown32'}, # unknown UINT16
6850
33 => +{'name' => 'unknown33'}, # unknown UINT16
6851
34 => +{'name' => 'unknown34'}, # unknown UINT16
6852
35 => +{'name' => 'unknown35'}, # unknown UINT16
6853
36 => +{'name' => 'unknown36'}, # unknown ENUM
6854
37 => +{'name' => 'unknown37'}, # unknown ENUM (array[7])
6855
38 => +{'name' => 'unknown38'}, # unknown ENUM (array[7])
6856
39 => +{'name' => 'unknown39'}, # unknown ENUM (array[7])
6857
40 => +{'name' => 'unknown40'}, # unknown UINT16Z
6858
41 => +{'name' => 'unknown41'}, # unknown UINT8 (array[7])
6859
42 => +{'name' => 'unknown42'}, # unknown ENUM
6860
43 => +{'name' => 'unknown43'}, # unknown ENUM
6861
44 => +{'name' => 'unknown44'}, # unknown UINT8Z
6862
47 => +{'name' => 'unknown47'}, # unknown ENUM
6863
48 => +{'name' => 'unknown48'}, # unknown ENUM
6864
},
6865
6866
);
6867
6868
my %msgtype_by_num = (
6869
13 => +{ # begins === Unknown messages === section
6870
'_number' => 13,
6871
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6872
1 => +{'name' => 'unknown1'}, # unknown ENUM
6873
2 => +{'name' => 'unknown2'}, # unknown UINT16
6874
3 => +{'name' => 'unknown3'}, # unknown ENUM
6875
4 => +{'name' => 'unknown4'}, # unknown UINT32
6876
5 => +{'name' => 'unknown5'}, # unknown SINT32
6877
6 => +{'name' => 'unknown6'}, # unknown SINT32
6878
7 => +{'name' => 'unknown7'}, # unknown ENUM
6879
8 => +{'name' => 'unknown8'}, # unknown UINT16
6880
9 => +{'name' => 'unknown9'}, # unknown ENUM
6881
10 => +{'name' => 'unknown10'}, # unknown UINT16
6882
11 => +{'name' => 'unknown11'}, # unknown UINT8
6883
12 => +{'name' => 'unknown12'}, # unknown ENUM
6884
13 => +{'name' => 'unknown13'}, # unknown ENUM
6885
14 => +{'name' => 'unknown14'}, # unknown ENUM
6886
15 => +{'name' => 'unknown15'}, # unknown ENUM
6887
16 => +{'name' => 'unknown16'}, # unknown ENUM
6888
17 => +{'name' => 'unknown17'}, # unknown ENUM
6889
18 => +{'name' => 'unknown18'}, # unknown ENUM
6890
19 => +{'name' => 'unknown19'}, # unknown UINT16
6891
25 => +{'name' => 'unknown25'}, # unknown ENUM
6892
27 => +{'name' => 'unknown27'}, # unknown ENUM
6893
30 => +{'name' => 'unknown30'}, # unknown ENUM
6894
31 => +{'name' => 'unknown31'}, # unknown UINT32
6895
32 => +{'name' => 'unknown32'}, # unknown UINT16
6896
33 => +{'name' => 'unknown33'}, # unknown UINT32
6897
34 => +{'name' => 'unknown34'}, # unknown ENUM
6898
50 => +{'name' => 'unknown50'}, # unknown ENUM
6899
51 => +{'name' => 'unknown51'}, # unknown ENUM
6900
52 => +{'name' => 'unknown52'}, # unknown UINT16
6901
53 => +{'name' => 'unknown53'}, # unknown ENUM
6902
56 => +{'name' => 'unknown56'}, # unknown ENUM
6903
},
6904
6905
14 => +{
6906
'_number' => 14,
6907
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6908
1 => +{'name' => 'unknown1'}, # unknown ENUM
6909
3 => +{'name' => 'unknown3'}, # unknown UINT8
6910
4 => +{'name' => 'unknown4'}, # unknown UINT8 (array[10])
6911
5 => +{'name' => 'unknown5'}, # unknown ENUM (array[10])
6912
6 => +{'name' => 'unknown6'}, # unknown STRING
6913
7 => +{'name' => 'unknown7'}, # unknown UINT16 (array[10])
6914
},
6915
6916
16 => +{
6917
'_number' => 16,
6918
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6919
1 => +{'name' => 'unknown1'}, # unknown ENUM
6920
2 => +{'name' => 'unknown2'}, # unknown UINT32
6921
3 => +{'name' => 'unknown3'}, # unknown ENUM
6922
},
6923
6924
17 => +{
6925
'_number' => 17,
6926
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6927
1 => +{'name' => 'unknown1'}, # unknown ENUM
6928
2 => +{'name' => 'unknown2'}, # unknown ENUM
6929
3 => +{'name' => 'unknown3'}, # unknown UINT16
6930
4 => +{'name' => 'unknown4'}, # unknown ENUM
6931
5 => +{'name' => 'unknown5'}, # unknown UINT16
6932
},
6933
6934
70 => +{
6935
'_number' => 70,
6936
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6937
0 => +{'name' => 'unknown0'}, # unknown ENUM
6938
1 => +{'name' => 'unknown1'}, # unknown ENUM
6939
2 => +{'name' => 'unknown2'}, # unknown ENUM
6940
3 => +{'name' => 'unknown3'}, # unknown ENUM
6941
4 => +{'name' => 'unknown4'}, # unknown ENUM
6942
5 => +{'name' => 'unknown5'}, # unknown ENUM
6943
6 => +{'name' => 'unknown6'}, # unknown ENUM
6944
7 => +{'name' => 'unknown7'}, # unknown ENUM
6945
8 => +{'name' => 'unknown8'}, # unknown ENUM
6946
9 => +{'name' => 'unknown9'}, # unknown ENUM
6947
10 => +{'name' => 'unknown10'}, # unknown ENUM
6948
11 => +{'name' => 'unknown11'}, # unknown ENUM
6949
12 => +{'name' => 'unknown12'}, # unknown ENUM
6950
13 => +{'name' => 'unknown13'}, # unknown ENUM
6951
14 => +{'name' => 'unknown14'}, # unknown ENUM
6952
15 => +{'name' => 'unknown15'}, # unknown ENUM
6953
},
6954
6955
71 => +{
6956
'_number' => 71,
6957
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6958
0 => +{'name' => 'unknown0'}, # unknown ENUM
6959
1 => +{'name' => 'unknown1'}, # unknown ENUM
6960
2 => +{'name' => 'unknown2'}, # unknown ENUM
6961
3 => +{'name' => 'unknown3'}, # unknown UINT16
6962
4 => +{'name' => 'unknown4'}, # unknown ENUM
6963
},
6964
6965
79 => +{
6966
'_number' => 79,
6967
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6968
0 => +{'name' => 'unknown0'}, # unknown UINT16
6969
1 => +{'name' => 'unknown1'}, # unknown UINT8
6970
2 => +{'name' => 'unknown2'}, # unknown UINT8
6971
3 => +{'name' => 'unknown3'}, # unknown UINT16
6972
4 => +{'name' => 'unknown4'}, # unknown ENUM
6973
5 => +{'name' => 'unknown5'}, # unknown ENUM
6974
6 => +{'name' => 'unknown6'}, # unknown UINT8
6975
7 => +{'name' => 'unknown7'}, # unknown SINT8
6976
8 => +{'name' => 'unknown8'}, # unknown UINT16
6977
9 => +{'name' => 'unknown9'}, # unknown UINT16
6978
10 => +{'name' => 'unknown10'}, # unknown UINT8
6979
11 => +{'name' => 'unknown11'}, # unknown UINT16
6980
12 => +{'name' => 'unknown12'}, # unknown UINT16
6981
13 => +{'name' => 'unknown13'}, # unknown UINT16
6982
14 => +{'name' => 'unknown14'}, # unknown UINT8
6983
},
6984
6985
113 => +{
6986
'_number' => 113,
6987
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6988
0 => +{'name' => 'unknown0'}, # unknown UINT16
6989
1 => +{'name' => 'unknown1'}, # unknown ENUM
6990
2 => +{'name' => 'unknown2'}, # unknown UINT32
6991
3 => +{'name' => 'unknown3'}, # unknown UINT32
6992
4 => +{'name' => 'unknown4'}, # unknown UINT32
6993
5 => +{'name' => 'unknown5'}, # unknown ENUM
6994
},
6995
6996
114 => +{
6997
'_number' => 114,
6998
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6999
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
7000
0 => +{'name' => 'unknown0'}, # unknown UINT16
7001
1 => +{'name' => 'unknown1'}, # unknown ENUM
7002
2 => +{'name' => 'unknown2'}, # unknown UINT32
7003
3 => +{'name' => 'unknown3'}, # unknown UINT32
7004
4 => +{'name' => 'unknown4'}, # unknown UINT32
7005
5 => +{'name' => 'unknown5'}, # unknown UINT32
7006
6 => +{'name' => 'unknown6'}, # unknown UINT32Z
7007
7 => +{'name' => 'unknown7'}, # unknown UINT32
7008
},
7009
7010
139 => +{
7011
'_number' => 139,
7012
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
7013
0 => +{'name' => 'unknown0'}, # unknown ENUM
7014
1 => +{'name' => 'unknown1'}, # unknown UINT16Z
7015
3 => +{'name' => 'unknown3'}, # unknown UINT8Z
7016
4 => +{'name' => 'unknown4'}, # unknown ENUM
7017
5 => +{'name' => 'unknown5'}, # unknown UINT16
7018
},
7019
7020
140 => +{
7021
'_number' => 140,
7022
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
7023
0 => +{'name' => 'unknown0'}, # unknown UINT8
7024
1 => +{'name' => 'unknown1'}, # unknown UINT8
7025
2 => +{'name' => 'unknown2'}, # unknown SINT32
7026
3 => +{'name' => 'unknown3'}, # unknown SINT32
7027
4 => +{'name' => 'unknown4'}, # unknown UINT8
7028
5 => +{'name' => 'unknown5'}, # unknown SINT32
7029
6 => +{'name' => 'unknown6'}, # unknown SINT32
7030
7 => +{'name' => 'unknown7'}, # unknown SINT32
7031
8 => +{'name' => 'unknown8'}, # unknown UINT8
7032
9 => +{'name' => 'unknown9'}, # unknown UINT16
7033
10 => +{'name' => 'unknown10'}, # unknown UINT16
7034
11 => +{'name' => 'unknown11'}, # unknown ENUM
7035
12 => +{'name' => 'unknown12'}, # unknown ENUM
7036
13 => +{'name' => 'unknown13'}, # unknown UINT8
7037
14 => +{'name' => 'unknown14'}, # unknown UINT16
7038
15 => +{'name' => 'unknown15'}, # unknown UINT16
7039
16 => +{'name' => 'unknown16'}, # unknown UINT16
7040
17 => +{'name' => 'unknown17'}, # unknown SINT8
7041
18 => +{'name' => 'unknown18'}, # unknown UINT8
7042
19 => +{'name' => 'unknown19'}, # unknown UINT8
7043
},
7044
7045
203 => +{
7046
'_number' => 203,
7047
0 => +{'name' => 'unknown0'}, # unknown ENUM
7048
1 => +{'name' => 'unknown1'}, # unknown ENUM
7049
2 => +{'name' => 'unknown2'}, # unknown ENUM
7050
},
7051
7052
);
7053
7054
my $mesg_name_vs_num = $named_type{mesg_num};
7055
7056
for my $msgname (keys %msgtype_by_name) {
7057
my $msgtype = $msgtype_by_name{$msgname};
7058
7059
$msgtype->{_name} = $msgname;
7060
$msgtype->{_number} = $mesg_name_vs_num->{$msgname};
7061
$msgtype_by_num{$msgtype->{_number}} = $msgtype;
7062
7063
for my $fldnum (grep {/^\d+$/} keys %$msgtype) {
7064
my $flddesc = $msgtype->{$fldnum};
7065
7066
$flddesc->{number} = $fldnum;
7067
$msgtype->{$flddesc->{name}} = $flddesc;
7068
}
7069
}
7070
7071
=head2 Constructor Methods
7072
7073
=over 4
7074
7075
=item new()
7076
7077
creates a new object and returns it.
7078
7079
=back
7080
7081
=cut
7082
7083
sub new {
7084
12
12
1
902337
my $class = shift;
7085
12
31
my $self = +{};
7086
12
63
bless $self, $class;
7087
12
86
$self->initialize(@_);
7088
7089
# defaults
7090
12
83
$self->use_gmtime(1);
7091
12
55
$self->semicircles_to_degree(1);
7092
12
2635
return $self
7093
}
7094
7095
=over 4
7096
7097
=item clone()
7098
7099
Returns a copy of a C instance.
7100
7101
C is experimental and support for it may be removed at any time. Use with caution particularly if there are open filehandles, it which case it is recommended to C before cloning.
7102
7103
It also does not return a full deep copy if any callbacks are registered, it creates a reference to them. There is no known way to make deep copies of anonymous subroutines in Perl (if you know of one, please make a pull request).
7104
7105
The main use for c is immediately after C, and C, to create a copy for later use.
7106
7107
=back
7108
7109
=cut
7110
7111
sub clone {
7112
1
1
1
9
my $self = shift;
7113
7114
1
984
require Clone;
7115
1
901
my $clone = Clone::clone( $self );
7116
1
5
return $clone
7117
}
7118
7119
=head2 Class methods
7120
7121
=over 4
7122
7123
=item profile_version_string()
7124
7125
returns a string representing the .FIT profile version on which this class based.
7126
7127
=back
7128
7129
=cut
7130
7131
my $profile_current = '21.141';
7132
my $protocol_current = '2.3'; # is there such a thing as current protocol for the class?
7133
# don't think so, pod was removed for protocol_* above
7134
7135
my $protocol_version_major_shift = 4;
7136
my $protocol_version_minor_mask = (1 << $protocol_version_major_shift) - 1;
7137
my $protocol_version_header_crc_started = _protocol_version_from_string("1.0");
7138
my $profile_version_scale = 100;
7139
7140
sub _protocol_version_from_string {
7141
18
18
54
my $s = shift;
7142
18
122
my ($major, $minor) = split /\./, $s, 2;
7143
18
50
159
return ($major + 0, $minor & $protocol_version_minor_mask) if wantarray;
7144
18
99
return ($major << $protocol_version_major_shift) | ($minor & $protocol_version_minor_mask)
7145
}
7146
7147
sub protocol_version {
7148
3
3
0
10
my $self = shift;
7149
3
9
my $version;
7150
3
50
12
if (@_) { $version = shift }
3
7
7151
0
0
else { $version = _protocol_version_from_string($protocol_current) }
7152
3
50
14
return ($version >> $protocol_version_major_shift, $version & $protocol_version_minor_mask) if wantarray;
7153
3
9
return $version
7154
}
7155
7156
sub _profile_version_from_string {
7157
23
23
5678
my $str = shift;
7158
23
50
55
croak '_profile_version_from_string() expects a string as argument' unless $str;
7159
23
64
my ($major, $minor) = split /\./, $str, 2;
7160
23
100
57
if ($minor >= 100) { $major += 1 } # kludge to deal with three-digit minor versions
15
26
7161
23
48
return $major * $profile_version_scale + $minor % $profile_version_scale
7162
}
7163
7164
sub profile_version {
7165
32
32
0
11840
my $self = shift;
7166
32
45
my $version;
7167
32
100
73
if (@_) {
7168
29
56
$version = shift;
7169
29
100
146
$version = _profile_version_from_string($version) if $version =~ /\./
7170
3
7
} else { $version = _profile_version_from_string($profile_current) }
7171
7172
32
100
106
if (wantarray) {
7173
21
59
my $major = int($version / $profile_version_scale);
7174
21
32
my $minor = $version % $profile_version_scale;
7175
21
100
48
if ($version >= 2200) { # kludge to deal with three-digit minor versions
7176
11
14
$major -= 1;
7177
11
12
$minor += 100
7178
}
7179
21
64
return ($major, $minor)
7180
}
7181
11
25
return $version
7182
}
7183
7184
sub profile_version_string {
7185
7
7
1
3526
my $self = shift;
7186
7
8
my @version;
7187
7
100
16
if (blessed $self) {
7188
1
50
4
croak 'fetch_header() has not been called yet to obtain the version from the header, call fetch_header() first' unless defined $self->{profile_version};
7189
1
50
3
croak 'object method expects no arguments' if @_;
7190
@version = profile_version(undef, $self->{profile_version} )
7191
1
3
} else {
7192
6
13
@version = profile_version(undef, @_)
7193
}
7194
7
34
return sprintf '%u.%03u', @version
7195
}
7196
7197
1
1
0
6
sub profile_version_major { profile_version( @_) };
7198
0
0
0
0
sub protocol_version_string { sprintf '%u.%u', ( protocol_version(@_) ) }
7199
0
0
0
0
sub protocol_version_major { protocol_version(@_) };
7200
7201
# CRC calculation routine taken from
7202
# Haruhiko Okumura, C gengo ni yoru algorithm dai jiten (1st ed.), GijutsuHyouronsha 1991.
7203
7204
my $crc_poly = 2 ** 16 + 2 ** 15 + 2 ** 2 + 2 ** 0; # CRC-16
7205
my ($crc_poly_deg, $crc_poly_rev);
7206
my ($x, $y, $i);
7207
for ($crc_poly_deg = 0, $x = $crc_poly ; $x >>= 1 ;) {
7208
++$crc_poly_deg;
7209
}
7210
my $crc_octets = int($crc_poly_deg / 8 + 0.5);
7211
for ($crc_poly_rev = 0, $y = 1, $x = 2 ** ($crc_poly_deg - 1) ; $x ;) {
7212
$crc_poly_rev |= $y if $x & $crc_poly;
7213
$y <<= 1;
7214
$x >>= 1;
7215
}
7216
my @crc_table = ();
7217
for ($i = 0 ; $i < 2 ** 8 ; ++$i) {
7218
my $r = $i;
7219
my $j;
7220
for ($j = 0 ; $j < 8 ; ++$j) {
7221
if ($r & 1) {
7222
$r = ($r >> 1) ^ $crc_poly_rev;
7223
} else {
7224
$r >>= 1;
7225
}
7226
}
7227
$crc_table[$i] = $r;
7228
}
7229
7230
# delete
7231
sub dump {
7232
0
0
0
0
my ($self, $s, $fh) = @_;
7233
0
0
my ($i, $d);
7234
0
0
for ($i = 0 ; $i < length($s) ;) {
7235
0
0
$fh->printf(' %03u', ord(substr($s, $i++, 1)));
7236
}
7237
}
7238
7239
# delete
7240
sub safe_isa {
7241
0
0
0
0
eval {$_[0]->isa($_[1])};
0
0
7242
}
7243
7244
# make internal
7245
# move to a section on internal accessors
7246
sub file_read {
7247
54
54
0
120
my $self = shift;
7248
54
100
113
if (@_) {
7249
18
89
$self->{file_read} = $_[0];
7250
} else {
7251
36
216
$self->{file_read};
7252
}
7253
}
7254
7255
# make internal (or add POD)
7256
# move to a section on internal accessors (or to object methods)
7257
sub file_size {
7258
1481
1481
0
2338
my $self = shift;
7259
1481
100
2764
if (@_) {
7260
13
52
$self->{file_size} = $_[0];
7261
} else {
7262
1468
3614
$self->{file_size};
7263
}
7264
}
7265
7266
# make internal (or add POD)
7267
# move to a section on internal accessors (or to object methods)
7268
sub file_processed {
7269
1450
1450
0
2221
my $self = shift;
7270
1450
100
2603
if (@_) {
7271
13
40
$self->{file_processed} = $_[0];
7272
} else {
7273
1437
3321
$self->{file_processed};
7274
}
7275
}
7276
7277
# make internal
7278
# move to a section on internal accessors
7279
sub offset {
7280
7707
7707
1
12152
my $self = shift;
7281
7707
100
12966
if (@_) {
7282
1605
3372
$self->{offset} = $_[0];
7283
} else {
7284
6102
12238
$self->{offset};
7285
}
7286
}
7287
7288
# make internal
7289
# move to a section on internal accessors
7290
sub buffer {
7291
5920
5920
0
10319
my $self = shift;
7292
5920
50
10483
if (@_) {
7293
0
0
$self->{buffer} = $_[0];
7294
} else {
7295
5920
12999
$self->{buffer};
7296
}
7297
}
7298
7299
# make internal
7300
# move to a section on internal accessors
7301
sub maybe_chained {
7302
20
20
0
38
my $self = shift;
7303
20
100
50
if (@_) {
7304
4
12
$self->{maybe_chained} = $_[0];
7305
} else {
7306
16
128
$self->{maybe_chained};
7307
}
7308
}
7309
7310
# make internal
7311
# move to a section on internal methods
7312
sub clear_buffer {
7313
26
26
0
48
my $self = shift;
7314
26
100
93
if ($self->offset > 0) {
7315
13
37
my $buffer = $self->{buffer};
7316
13
50
69
$self->crc_calc(length($$buffer)) if !defined $self->crc;
7317
13
75
$self->file_processed($self->file_processed + $self->offset);
7318
13
68
substr($$buffer, 0, $self->offset) = '';
7319
13
41
$self->offset(0)
7320
}
7321
26
54
return 1
7322
}
7323
7324
=head2 Object methods
7325
7326
=over 4
7327
7328
=item file( $filename )
7329
7330
returns the name of a .FIT file. Sets the name to I<$filename> if called with an argument (raises an exception if the file does not exist).
7331
7332
=back
7333
7334
=cut
7335
7336
sub file {
7337
38
38
1
5272
my $self = shift;
7338
38
100
124
if (@_) {
7339
12
29
my $fname = $_[0];
7340
12
50
496
croak "file $fname specified in file() does not exist: $!" unless -f $fname;
7341
12
68
$self->{file} = $fname
7342
}
7343
return $self->{file}
7344
38
116
}
7345
7346
=over 4
7347
7348
=item open()
7349
7350
opens the .FIT file.
7351
7352
=back
7353
7354
=cut
7355
7356
sub open {
7357
13
13
1
636
my $self = shift;
7358
13
60
my $fn = $self->file;
7359
7360
13
50
49
if ($fn ne '') {
7361
13
265
my $fh = $self->fh;
7362
7363
13
50
142
if ($fh->open("< $fn")) {
7364
13
50
1427
if (binmode $fh, ':raw') {
7365
13
69
1;
7366
} else {
7367
0
0
$self->error("binmode \$fh, ':raw': $!");
7368
}
7369
} else {
7370
0
0
$self->error("\$fh->open(\"< $fn\"): $!");
7371
}
7372
} else {
7373
0
0
$self->error('no file name given');
7374
}
7375
}
7376
7377
# make internal
7378
# move to a section on internal accessors
7379
sub fh {
7380
2939
2939
0
4581
my $self = shift;
7381
2939
50
5428
if (@_) {
7382
0
0
$self->{fh} = $_[0];
7383
} else {
7384
2939
11110
$self->{fh};
7385
}
7386
}
7387
7388
# make internal
7389
# move to a section on internal accessors
7390
sub EOF {
7391
10
10
20
my $self = shift;
7392
10
100
28
if (@_) {
7393
8
26
$self->{EOF} = $_[0];
7394
} else {
7395
2
29
$self->{EOF};
7396
}
7397
}
7398
7399
# make internal
7400
# move to a section on internal accessors
7401
sub end_of_chunk {
7402
9
9
0
20
my $self = shift;
7403
9
100
31
if (@_) {
7404
8
119
$self->{end_of_chunk} = $_[0];
7405
} else {
7406
1
4
$self->{end_of_chunk};
7407
}
7408
}
7409
7410
# make internal
7411
# move to a section on internal functions
7412
sub fill_buffer {
7413
26
26
0
72
my $self = shift;
7414
26
94
my $buffer = $self->buffer;
7415
26
50
96
croak 'fill_buffer() expects no argument' if @_;
7416
7417
26
123
$self->clear_buffer;
7418
7419
26
80
my $n = $self->fh->read($$buffer, BUFSIZ, length($$buffer));
7420
7421
26
100
1237
if ($n > 0) {
7422
18
109
$self->file_read($self->file_read + $n);
7423
7424
18
100
113
if (defined $self->file_size) {
7425
5
50
24
if (defined $self->crc) {
7426
5
26
$self->crc_calc($n);
7427
} else {
7428
0
0
$self->crc_calc(length($$buffer));
7429
}
7430
}
7431
} else {
7432
8
50
64
if (defined $n) {
7433
8
80
$self->error("unexpected EOF");
7434
8
36
$self->EOF(1);
7435
} else {
7436
0
0
$self->error("read(fh): $!");
7437
}
7438
return undef
7439
8
81
}
7440
18
110
return 1
7441
}
7442
7443
# move to a section on internal functions
7444
sub _buffer_needs_updating {
7445
3016
3016
5985
my ($self, $bytes_needed) = @_;
7446
3016
5635
my ($buffer, $offset) = ($self->buffer, $self->offset); # easier to debug with variables
7447
3016
100
6584
if ( length($$buffer) - $offset < $bytes_needed ) { return 1 }
26
151
7448
2990
8025
else { return 0 }
7449
}
7450
7451
my $header_template = 'C C v V V';
7452
my $header_length = length(pack($header_template));
7453
7454
sub FIT_HEADER_LENGTH {
7455
0
0
1
0
$header_length;
7456
}
7457
7458
my $FIT_signature_string = '.FIT';
7459
my $FIT_signature = unpack('V', $FIT_signature_string);
7460
7461
my $header_crc_template = 'v';
7462
my $header_crc_length = length(pack($header_crc_template));
7463
7464
=over 4
7465
7466
=item fetch_header()
7467
7468
reads .FIT file header, and returns an array of the file size (excluding the trailing CRC-16), the protocol version, the profile version, extra octets in the header other than documented 4 values, the header CRC-16 recorded in the header, and the calculated header CRC-16.
7469
7470
=back
7471
7472
=cut
7473
7474
sub fetch_header {
7475
13
13
1
65
my $self = shift;
7476
13
50
57
croak 'call the open() method before fetching the header' if $self->fh->tell < 0;
7477
13
50
161
croak '.FIT file header has already been fetched' if $self->fh->tell > 0;
7478
7479
13
133
my $buffer = $self->buffer;
7480
7481
13
50
57
if ( $self->_buffer_needs_updating( $header_length ) ) {
7482
13
50
67
$self->fill_buffer or return undef
7483
}
7484
13
55
my $h_min = substr($$buffer, $self->offset, $header_length);
7485
13
90
my ($h_len, $proto_ver, $prof_ver, $f_len, $sig) = unpack($header_template, $h_min);
7486
13
41
my $f_size = $f_len + $h_len;
7487
13
44
$self->offset($self->offset + $header_length);
7488
7489
13
25
my ($extra, $header_extra_bytes, $crc_expected, $crc_calculated);
7490
13
29
$header_extra_bytes = $h_len - $header_length; # headers are now typically 14 bytes instead of 12
7491
7492
13
50
62
if ($header_extra_bytes < 0) {
7493
0
0
$self->error("not a .FIT header ($h_len < $header_length)");
7494
return ()
7495
0
0
}
7496
7497
13
50
43
if ($header_extra_bytes) {
7498
13
50
77
if ( $self->_buffer_needs_updating( $header_extra_bytes ) ) {
7499
0
0
0
$self->fill_buffer or return undef
7500
}
7501
13
143
$extra = substr($$buffer, $self->offset, $header_extra_bytes );
7502
13
42
$self->offset($self->offset + $header_extra_bytes );
7503
}
7504
7505
13
50
188
if ($sig != $FIT_signature) {
7506
$self->error("not a .FIT header (" .
7507
0
0
0
0
join('', map {($_ ne "\\" && 0x20 >= ord($_) && ord($_) <= 0x7E) ? $_ : sprintf("\\x%02X", ord($_))} split //, pack('V', $sig))
0
0
7508
. " ne '$FIT_signature_string')");
7509
return ()
7510
0
0
}
7511
7512
13
50
33
160
if ($proto_ver >= $protocol_version_header_crc_started && length($extra) >= $header_crc_length) {
7513
13
56
$crc_expected = unpack($header_crc_template, substr($extra, -$header_crc_length));
7514
13
45
substr($extra, -$header_crc_length) = '';
7515
13
74
$crc_calculated = $self->crc_of_string(0, \$h_min, 0, $header_length);
7516
}
7517
7518
13
106
$self->file_size($f_size);
7519
13
50
63
unless (defined $self->crc) {
7520
13
54
$self->crc(0);
7521
13
56
$self->crc_calc(length($$buffer));
7522
}
7523
7524
13
86
$self->{profile_version} = $prof_ver;
7525
13
151
return ($f_size, $proto_ver, $prof_ver, $extra, $crc_expected, $crc_calculated)
7526
}
7527
7528
=over 4
7529
7530
=item fetch()
7531
7532
reads a message in the .FIT file, and returns C<1> on success, or C on failure or EOF. C must have been called before the first attempt to C after opening the file.
7533
7534
If a data message callback is registered, C will return the value returned by the callback. It is therefore important to define explicit return statements and values in any callback (this includes returning true if that is the desired outcome after C).
7535
7536
=back
7537
7538
=cut
7539
7540
sub fetch {
7541
1432
1432
1
97951
my $self = shift;
7542
1432
50
3664
croak 'call the fetch_header() method before calling fetch()' if $self->fh->tell == 0;
7543
1432
50
10196
croak 'open() and fetch_header() methods need to be called before calling fetch()' if $self->fh->tell < 0;
7544
7545
1432
8461
my $buffer = $self->buffer;
7546
7547
1432
100
3439
if ( $self->_buffer_needs_updating( $crc_octets ) ) {
7548
8
50
74
$self->fill_buffer or return undef
7549
}
7550
1424
2929
my $i = $self->offset;
7551
1424
3227
my $j = $self->file_processed + $i;
7552
7553
1424
2175
my $ret_val;
7554
7555
1424
100
33
3456
if ($j < $self->file_size) {
50
7556
1416
3241
my $record_header = ord(substr($$buffer, $i, 1));
7557
1416
2105
my $local_msg_type;
7558
7559
1416
50
3713
if ($record_header & $rechd_mask_compressed_timestamp_header) {
100
7560
0
0
$local_msg_type = ($record_header & $rechd_mask_cth_local_message_type) >> $rechd_offset_cth_local_message_type
7561
} elsif ($record_header & $rechd_mask_definition_message) {
7562
143
465
$ret_val = $self->fetch_definition_message; # always 1
7563
143
1123
return $ret_val
7564
} else {
7565
1273
2260
$local_msg_type = $record_header & $rechd_mask_local_message_type
7566
}
7567
7568
1273
3202
my $desc = $self->data_message_descriptor->[$local_msg_type];
7569
7570
1273
100
2814
if (ref $desc eq 'HASH') {
7571
1272
3101
$ret_val = $self->fetch_data_message($desc)
7572
} else {
7573
1
28
$ret_val = $self->error(sprintf("%d at %ld: not defined", $record_header, $j))
7574
}
7575
} elsif (!$self->maybe_chained && $j > $self->file_size) {
7576
0
0
$self->trailing_garbages($self->trailing_garbages + length($$buffer) - $i);
7577
0
0
$self->offset(length($$buffer));
7578
0
0
$ret_val = 1
7579
} else {
7580
8
50
48
$self->crc_calc(length($$buffer)) if !defined $self->crc;
7581
7582
8
18
my ($crc_expected, $k);
7583
7584
8
38
for ($crc_expected = 0, $k = $crc_octets ; $k > 0 ;) {
7585
16
65
$crc_expected = ($crc_expected << 8) + ord(substr($$buffer, $i + --$k, 1));
7586
}
7587
7588
8
40
$self->crc_expected($crc_expected);
7589
8
46
$self->offset($i + $crc_octets);
7590
8
38
$self->end_of_chunk(1);
7591
8
54
$ret_val = !$self->maybe_chained
7592
}
7593
1281
5811
return $ret_val
7594
}
7595
7596
sub error_callback { # consider adding POD for error_callback otherwise make it internal (_error_callback)
7597
1
1
0
63
my $self = shift;
7598
1
50
4
if (@_) {
7599
# if (&safe_isa($_[0], 'CODE')) {
7600
1
50
33
10
if (ref $_[0] and ref $_[0] eq 'CODE') {
7601
1
10
$self->{error_callback_argv} = [@_[1 .. $#_]];
7602
1
5
$self->{error_callback} = $_[0];
7603
} else {
7604
0
0
undef;
7605
}
7606
} else {
7607
0
0
$self->{error_callback};
7608
}
7609
}
7610
7611
=over 4
7612
7613
=item error()
7614
7615
returns an error message recorded by a method.
7616
7617
=back
7618
7619
=cut
7620
7621
sub error {
7622
13
13
1
29
my $self = shift;
7623
13
50
48
if (@_) {
7624
13
43
my ($p, $fn, $l, $subr, $fit);
7625
7626
13
102
(undef, $fn, $l) = caller(0);
7627
13
70
($p, undef, undef, $subr) = caller(1);
7628
13
61
$fit = $self->file;
7629
13
50
62
$fit .= ': ' if $fit ne '';
7630
7631
13
60
$self->{error} = "${p}::$subr\#$l\@$fn: $fit$_[0]";
7632
7633
# if (&safe_isa($self->{error_callback}, 'CODE')) {
7634
# my $argv = &safe_isa($self->{error_callback_argv}, 'ARRAY') ? $self->{error_callback_argv} : [];
7635
13
32
my $is_cb = $self->{error_callback};
7636
13
31
my $is_cb_argv = $self->{error_callback_argv};
7637
13
50
33
136
if (ref $is_cb and ref $is_cb eq 'CODE') {
7638
0
0
0
0
my $argv = (ref $is_cb_argv and ref $is_cb_argv eq 'ARRAY') ? $is_cb_argv : [];
7639
7640
0
0
$self->{error_callback}->($self, @$argv);
7641
} else {
7642
13
238
undef;
7643
}
7644
} else {
7645
0
0
$self->{error};
7646
}
7647
}
7648
7649
=over 4
7650
7651
=item crc()
7652
7653
CRC-16 calculated from the contents of a .FIT file.
7654
7655
=back
7656
7657
=cut
7658
7659
sub crc {
7660
89
89
1
154
my $self = shift;
7661
89
100
204
if (@_) {
7662
31
146
$self->{crc} = $_[0];
7663
} else {
7664
58
252
$self->{crc};
7665
}
7666
}
7667
7668
sub crc_of_string {
7669
31
31
0
84
my ($self, $crc, $p, $b, $n) = @_;
7670
31
94
my $e = $b + $n;
7671
31
195
while ($b < $e) {
7672
97812
228162
$crc = ($crc >> 8) ^ $crc_table[($crc & (2 ** 8 - 1)) ^ ord(substr($$p, $b++, 1))];
7673
}
7674
31
270
$crc;
7675
}
7676
7677
sub crc_calc {
7678
18
18
0
46
my ($self, $m) = @_;
7679
18
99
my $over = $self->file_read - $self->file_size;
7680
18
100
92
$over = 0 if $over < 0;
7681
7682
18
50
114
if ($m > $over) {
7683
18
66
my $buffer = $self->buffer;
7684
18
54
$self->crc($self->crc_of_string($self->crc, $buffer, length($$buffer) - $m, $m - $over));
7685
}
7686
}
7687
7688
=over 4
7689
7690
=item crc_expected()
7691
7692
CRC-16 attached to the end of a .FIT file. Only available after all contents of the file has been read.
7693
7694
=back
7695
7696
=cut
7697
7698
sub crc_expected {
7699
9
9
1
21
my $self = shift;
7700
9
100
27
if (@_) {
7701
8
48
$self->{crc_expected} = $_[0];
7702
} else {
7703
1
3
$self->{crc_expected};
7704
}
7705
}
7706
7707
=over 4
7708
7709
=item trailing_garbages()
7710
7711
number of octets after CRC-16, 0 usually.
7712
7713
=back
7714
7715
=cut
7716
7717
sub trailing_garbages {
7718
1
1
1
2
my $self = shift;
7719
1
50
4
if (@_) {
7720
0
0
$self->{trailing_garbages} = $_[0];
7721
} else {
7722
1
3
$self->{trailing_garbages};
7723
}
7724
}
7725
7726
sub numeric_date_time {
7727
682
682
0
1064
my $self = shift;
7728
682
100
1351
if (@_) {
7729
7
27
$self->{numeric_date_time} = $_[0];
7730
} else {
7731
675
1927
$self->{numeric_date_time};
7732
}
7733
}
7734
7735
sub date_string {
7736
675
675
0
1430
my ($self, $time) = @_;
7737
675
50
1721
my ($s, $mi, $h, $d, $mo, $y, $gmt) = $self->use_gmtime ? ((gmtime($time))[0 .. 5], 'Z') : (localtime($time))[0 .. 5];
7738
675
15341
sprintf('%04u-%02u-%02uT%02u:%02u:%02u%s', $y + 1900, $mo + 1, $d, $h, $mi, $s, $gmt);
7739
}
7740
7741
sub named_type_value {
7742
1038
1038
0
4877
my ($self, $type_name, $val) = @_;
7743
1038
2694
my $typedesc = $named_type{$type_name};
7744
7745
1038
100
4039
if (ref $typedesc ne 'HASH') {
100
100
7746
4
47
$self->error("$type_name is not a named type");
7747
} elsif ($typedesc->{_mask}) {
7748
22
100
192
if ($val !~ /^[-+]?\d+$/) {
7749
3
7
my $num = 0;
7750
7751
3
16
for my $expr (split /,/, $val) {
7752
9
69
$expr =~ s/^.*=//;
7753
7754
9
50
26
if ($expr =~ s/^0[xX]//) {
7755
0
0
$num |= hex($expr);
7756
} else {
7757
9
24
$num |= $expr + 0;
7758
}
7759
}
7760
7761
3
12
$num;
7762
} else {
7763
19
43
my $mask = 0;
7764
19
73
my @key;
7765
7766
19
168
for my $key (sort {$typedesc->{$b} <=> $typedesc->{$a}} grep {/^[A-Za-z]/} keys %$typedesc) {
51
193
152
446
7767
57
340
push @key, $key . '=' . ($val & $typedesc->{$key});
7768
57
123
$mask |= $typedesc->{$key};
7769
}
7770
7771
19
105
my $rest = $val & ~$mask & ((1 << ($size[$typedesc->{_base_type}] * 8)) - 1);
7772
7773
19
50
69
if ($rest) {
50
7774
0
0
my $width = $size[$typedesc->{_base_type}] * 2;
7775
7776
0
0
join(',', @key, sprintf("0x%0${width}X", $rest));
7777
} elsif (@key) {
7778
19
143
join(',', @key);
7779
} else {
7780
0
0
0;
7781
}
7782
}
7783
} elsif ($type_name eq 'date_time') {
7784
679
100
33
6484
if ($val !~ /^[-+]?\d+$/) {
50
7785
4
39
my ($y, $mo, $d, $h, $mi, $s, $gmt) = $val =~ /(\d+)\D+(\d+)\D+(\d+)\D+(\d+)\D+(\d+)\D+(\d+)([zZ]?)/;
7786
7787
4
50
46
($gmt ne '' ? timegm($s, $mi, $h, $d, $mo - 1, $y - 1900) : timelocal($s, $mi, $h, $d, $mo - 1, $y - 1900)) + $typedesc->{_offset};
7788
} elsif ($val >= $typedesc->{_min} && $val != $invalid[$typedesc->{_base_type}]) {
7789
675
100
2018
if ($self->numeric_date_time) {
7790
9
31
$val - $typedesc->{_offset};
7791
} else {
7792
666
1766
$self->date_string($val - $typedesc->{_offset});
7793
}
7794
} else {
7795
0
0
undef;
7796
}
7797
} else {
7798
333
1264
$typedesc->{$val};
7799
}
7800
}
7801
7802
sub data_message_descriptor {
7803
1416
1416
0
2347
my $self = shift;
7804
7805
1416
50
2659
if (@_) {
7806
0
0
$self->{data_message_descriptor} = $_[0];
7807
} else {
7808
1416
100
4175
$self->{data_message_descriptor} = [] if ref $self->{data_message_descriptor} ne 'ARRAY';
7809
1416
4138
$self->{data_message_descriptor};
7810
}
7811
}
7812
7813
sub data_message_callback {
7814
202
202
0
512
$_[0]->{data_message_callback};
7815
}
7816
7817
=over 4
7818
7819
=item data_message_callback_by_num(I, I[, I, ...])
7820
7821
register a function I which is called when a data message with the messag number I is fetched.
7822
7823
=back
7824
7825
=cut
7826
7827
my $msgnum_anon = $invalid[FIT_UINT16];
7828
my $msgname_anon = '';
7829
7830
sub data_message_callback_by_num {
7831
0
0
1
0
my $self = shift;
7832
0
0
my $num = shift;
7833
0
0
my $cbmap = $self->data_message_callback;
7834
0
0
my ($msgtype, $name);
7835
7836
0
0
0
if ($num == $msgnum_anon) {
0
0
7837
0
0
0
if (@_) {
7838
0
0
0
if (ref $_[0] eq 'CODE') {
7839
0
0
$cbmap->{$msgname_anon} = $cbmap->{$msgnum_anon} = [@_];
7840
} else {
7841
0
0
$self->error('not a CODE');
7842
}
7843
} else {
7844
0
0
my %res;
7845
0
0
foreach $num (keys %msgtype_by_num) {
7846
0
0
my $cb = $cbmap->{$num};
7847
0
0
0
ref $cb eq 'ARRAY' and $res{$num} = [@$cb];
7848
}
7849
0
0
\%res;
7850
}
7851
} elsif (!defined($msgtype = $msgtype_by_num{$num})) {
7852
0
0
$self->error("$num is not a message type number");
7853
} elsif (@_) {
7854
0
0
0
if (ref $_[0] eq 'CODE') {
7855
0
0
$cbmap->{$num} = [@_];
7856
0
0
0
$msgtype->{_name} ne '' and $cbmap->{$msgtype->{_name}} = $cbmap->{$num};
7857
0
0
$cbmap->{$num};
7858
} else {
7859
0
0
$self->error('not a CODE');
7860
}
7861
} else {
7862
0
0
my $cb = $cbmap->{$num};
7863
0
0
0
ref $cb eq 'ARRAY' ? [@$cb] : [];
7864
}
7865
}
7866
7867
=over 4
7868
7869
=item data_message_callback_by_name(I, I[, I, ...])
7870
7871
register a function I which is called when a data message with the name I is fetched.
7872
7873
=back
7874
7875
=cut
7876
7877
sub data_message_callback_by_name {
7878
59
59
1
423
my $self = shift;
7879
59
107
my $name = shift;
7880
59
147
my $cbmap = $self->data_message_callback;
7881
59
93
my $msgtype;
7882
7883
59
100
414
if ($name eq $msgname_anon) {
50
50
7884
7
100
36
if (@_) {
7885
5
50
19
if (ref $_[0] eq 'CODE') {
7886
5
37
$cbmap->{$msgname_anon} = $cbmap->{$msgnum_anon} = [@_];
7887
} else {
7888
0
0
$self->error('not a CODE');
7889
}
7890
} else {
7891
2
5
my %res;
7892
2
100
foreach $name (keys %msgtype_by_name) {
7893
248
295
my $cb = $cbmap->{$name};
7894
248
100
416
ref $cb eq 'ARRAY' and $res{$name} = [@$cb];
7895
}
7896
2
24
\%res;
7897
}
7898
} elsif (!defined($msgtype = $msgtype_by_name{$name})) {
7899
0
0
$self->error("$name is not a message type name");
7900
} elsif (@_) {
7901
52
50
139
if (ref $_[0] eq 'CODE') {
7902
52
385
$cbmap->{$msgtype->{_number}} = $cbmap->{$name} = [@_];
7903
} else {
7904
0
0
$self->error('not a CODE');
7905
}
7906
} else {
7907
0
0
my $cb = $cbmap->{$name};
7908
0
0
0
ref $cb eq 'ARRAY' ? [@$cb] : [];
7909
}
7910
}
7911
7912
sub undocumented_field_name {
7913
790
790
0
1660
my ($self, $index, $size, $type, $i_string) = @_;
7914
# 'xxx' . $i_string . '_' . $index . '_' . $size . '_' . $type;
7915
790
2092
'xxx' . $index;
7916
}
7917
7918
sub syscallback_devdata_id {
7919
0
0
0
0
my ($self, $desc, $v) = @_;
7920
0
0
my ($i_id, $T_id, $c_id, $i_index) = @$desc{qw(i_application_id T_application_id c_application_id i_developer_data_index)};
7921
0
0
my ($emsg, $warn);
7922
7923
0
0
0
0
if (!defined $i_id) {
0
0
7924
0
0
$emsg = "no application_id";
7925
0
0
$warn = 1;
7926
} elsif ($T_id != FIT_UINT8 && $T_id != FIT_BYTE) {
7927
0
0
croak "There is a bug here, this should be resolved soon";
7928
# $type_name has not been declared in this scope need to figure out what it should be
7929
# $emsg = "base type of application_id is $type_name [$T_id] ($T_id)";
7930
} elsif (!defined $i_index) {
7931
0
0
$emsg = "no developer_data_index";
7932
}
7933
7934
0
0
0
if ($emsg ne '') {
7935
0
0
0
if ($warn) {
7936
0
0
$self->error("suspicious developer data id message ($emsg)");
7937
} else {
7938
0
0
$self->error("broken developer data id message ($emsg)");
7939
0
0
return undef;
7940
}
7941
}
7942
7943
0
0
my $devdata_by_index = $self->{devdata_by_index};
7944
0
0
0
ref $devdata_by_index eq 'HASH' or $devdata_by_index = $self->{devdata_by_index} = +{};
7945
7946
0
0
my $devdata_by_id = $self->{devdata_by_id};
7947
0
0
0
ref $devdata_by_id eq 'HASH' or $devdata_by_id = $self->{devdata_by_id} = +{};
7948
7949
0
0
my $id;
7950
0
0
0
if ($T_id == FIT_UINT8) {
7951
0
0
$id = pack('C*', @$v[$i_id .. ($i_id + $c_id - 1)]);
7952
} else {
7953
0
0
$id = $v->[$i_id];
7954
}
7955
7956
0
0
my %devdata = (id => $id, index => $v->[$i_index]);
7957
0
0
$devdata_by_id->{$devdata{id}} = $devdata_by_index->{$devdata{index}} = \%devdata;
7958
}
7959
7960
sub syscallback_devdata_field_desc {
7961
0
0
0
0
my ($self, $desc, $v) = @_;
7962
7963
my ($i_index, $I_index, $i_field_num, $I_field_num,
7964
$i_base_type_id, $T_base_type_id, $I_base_type_id,
7965
$i_field_name, $T_field_name, $c_field_name)
7966
0
0
= @$desc{qw(i_developer_data_index I_developer_data_index i_field_definition_number I_field_definition_number
7967
i_fit_base_type_id T_fit_base_type_id I_fit_base_type_id
7968
i_field_name T_field_name c_field_name)};
7969
7970
0
0
my ($emsg, $warn, $o_name);
7971
7972
0
0
0
0
if (!defined $i_index) {
0
0
0
0
0
7973
0
0
$emsg = 'no developer_data_index';
7974
} elsif (!defined $i_field_num) {
7975
0
0
$emsg = 'no field_num';
7976
} elsif (!defined $i_base_type_id) {
7977
0
0
$emsg = 'no base_type_id';
7978
} elsif ($T_base_type_id != FIT_UINT8) {
7979
0
0
croak "There is a bug here, this should be resolved soon";
7980
# $type_name has not been declared in this scope need to figure out what it should be
7981
# $emsg = "base type of base_type_id is $type_name [$T_base_type_id] ($T_base_type_id)";
7982
} elsif (!defined $i_field_name) {
7983
0
0
$emsg = 'no field_name';
7984
0
0
$warn = 1;
7985
} elsif ($T_field_name != FIT_STRING || $c_field_name <= 0) {
7986
0
0
$emsg = "field_name is not a non-empty string";
7987
0
0
$warn = 1;
7988
} else {
7989
0
0
$o_name = _string_value($v, $i_field_name, $c_field_name);
7990
}
7991
7992
0
0
0
if ($emsg ne '') {
7993
0
0
0
if ($warn) {
7994
0
0
$self->error("suspicious field description message ($emsg)");
7995
} else {
7996
0
0
$self->error("broken field description message ($emsg)");
7997
0
0
return undef;
7998
}
7999
}
8000
8001
0
0
my $base_type = $v->[$i_base_type_id];
8002
8003
0
0
0
if ($base_type == $I_base_type_id) {
8004
0
0
$self->error("invalid base type ($base_type)");
8005
0
0
return undef;
8006
}
8007
8008
0
0
0
if ($base_type < 0) {
8009
0
0
$self->error("unknown base type ($base_type)");
8010
0
0
return undef;
8011
}
8012
8013
0
0
$base_type &= $deffld_mask_type;
8014
8015
0
0
0
unless ($base_type <= FIT_BASE_TYPE_MAX) {
8016
0
0
$self->error("unknown base type ($base_type)");
8017
0
0
return undef;
8018
}
8019
8020
0
0
my $devdata_by_index = $self->{devdata_by_index};
8021
8022
0
0
0
unless (ref $devdata_by_index eq 'HASH') {
8023
0
0
$self->error('no developer data id message before a field description message');
8024
0
0
return undef;
8025
}
8026
8027
0
0
my $index = $v->[$i_index];
8028
8029
0
0
0
if ($index == $I_index) {
8030
0
0
$self->error("invalid developer data index ($index)");
8031
0
0
return undef;
8032
}
8033
8034
0
0
my $num = $v->[$i_field_num];
8035
8036
0
0
0
if ($num == $I_field_num) {
8037
0
0
$self->error("invalid field definition number ($num)");
8038
0
0
return undef;
8039
}
8040
8041
0
0
my $devdata = $devdata_by_index->{$index};
8042
8043
0
0
0
unless (ref $devdata eq 'HASH') {
8044
0
0
$self->error("No developer data id message with the index $index before a field description message");
8045
0
0
return undef;
8046
}
8047
8048
0
0
my $field_desc_by_num = $devdata->{field_desc_by_num};
8049
0
0
0
ref $field_desc_by_num eq 'HASH' or $field_desc_by_num = $devdata->{field_desc_by_num} = +{};
8050
8051
0
0
my $field_desc_by_name = $devdata->{field_desc_by_name};
8052
0
0
0
ref $field_desc_by_name eq 'HASH' or $field_desc_by_name = $devdata->{field_desc_by_name} = +{};
8053
8054
0
0
my $name = $o_name;
8055
8056
0
0
0
if (defined $name) {
8057
0
0
$name =~ s/\s+/_/g;
8058
0
0
$name =~ s/\W/sprintf('_%02x_', ord($&))/ge;
0
0
8059
}
8060
8061
0
0
my %fdesc = (
8062
'_index' => $index,
8063
'_num' => $num,
8064
'_name' => $name,
8065
'field_name' => $o_name,
8066
'_type' => $base_type,
8067
);
8068
8069
0
0
for my $i_aname (grep {/^i_/} keys %$desc) {
0
0
8070
0
0
0
if ($i_aname !~ /^i_(developer_data_index|field_definition_number|fit_base_type_id|field_name)$/) {
8071
0
0
my $i = $desc->{$i_aname};
8072
0
0
my $aname = $i_aname;
8073
8074
0
0
$aname =~ s/^i_//;
8075
8076
0
0
my $I_aname = 'I_' . $aname;
8077
0
0
my $T_aname = 'T_' . $aname;
8078
0
0
my $c_aname = 'c_' . $aname;
8079
8080
0
0
0
if ($desc->{$T_aname} == FIT_STRING) {
0
8081
0
0
$fdesc{$aname} = _string_value($v, $i, $desc->{$c_aname});
8082
} elsif ($v->[$i] != $desc->{$I_aname}) {
8083
0
0
$fdesc{$aname} = $v->[$i];
8084
}
8085
}
8086
}
8087
8088
0
0
0
defined $name and $field_desc_by_name->{$name} = \%fdesc;
8089
0
0
$field_desc_by_num->{$num} = \%fdesc;
8090
}
8091
8092
sub add_endian_converter {
8093
3410
3410
0
6930
my ($self, $endian, $type, $c, $i_string, $cvt) = @_;
8094
8095
3410
50
33
7761
if ($endian != $my_endian && $size[$type] > 1) {
8096
0
0
my ($p, $unp, $n);
8097
8098
0
0
0
if ($size[$type] == 2) {
0
8099
0
0
($p, $unp) = (qw(n v));
8100
} elsif ($size[$type] == 4) {
8101
0
0
($p, $unp) = (qw(N V));
8102
} else {
8103
0
0
($p, $unp, $n) = (qw(N V), 2);
8104
}
8105
8106
0
0
push @$cvt, $p . $n, $unp . $n, $i_string, $size[$type], $c;
8107
0
0
1;
8108
} else {
8109
3410
5420
0;
8110
}
8111
}
8112
8113
sub fetch_definition_message {
8114
143
143
0
220
my $self = shift;
8115
143
318
my $buffer = $self->buffer;
8116
8117
143
50
323
if ( $self->_buffer_needs_updating( $defmsg_min_length ) ) {
8118
0
0
0
$self->fill_buffer or return undef
8119
}
8120
143
328
my $i = $self->offset;
8121
143
1556
my ($record_header, $reserved, $endian, $msgnum, $nfields) = unpack($defmsg_min_template, substr($$buffer, $i, $defmsg_min_length));
8122
8123
143
50
567
$endian = $endian ? 1 : 0;
8124
143
388
$self->offset($i + $defmsg_min_length);
8125
8126
143
270
my $len = $nfields * $deffld_length;
8127
8128
143
50
406
if ( $self->_buffer_needs_updating( $len ) ) {
8129
0
0
0
$self->fill_buffer or return undef
8130
}
8131
143
304
$i = $self->offset;
8132
143
50
456
$msgnum = unpack('n', pack('v', $msgnum)) if $endian != $my_endian;
8133
8134
143
544
my $msgtype = $msgtype_by_num{$msgnum};
8135
143
428
my $cbmap = $self->data_message_callback;
8136
143
251
my $e = $i + $len;
8137
143
284
my ($cb, %desc, $i_array, $i_array_t, $i_string, @cvt, @pi);
8138
8139
143
630
$desc{local_message_type} = $record_header & $rechd_mask_local_message_type;
8140
143
446
$desc{message_number} = $msgnum;
8141
143
100
100
1195
$desc{message_name} = $msgtype->{_name} if ref $msgtype eq 'HASH' && exists $msgtype->{_name};
8142
143
100
517
$cb = $cbmap->{$msgnum} if ref $cbmap->{$msgnum} eq 'ARRAY';
8143
143
100
440
$cb = $cbmap->{$msgnum_anon} if ref $cb ne 'ARRAY';
8144
143
100
450
$desc{callback} = $cb if ref $cb eq 'ARRAY';
8145
143
334
$desc{endian} = $endian;
8146
143
403
$desc{template} = 'C';
8147
143
447
$self->data_message_descriptor->[$desc{local_message_type}] = \%desc;
8148
8149
143
506
for ($i_array = $i_array_t = $i_string = 1 ; $i + $deffld_length <= $e ; $i += $deffld_length) {
8150
3410
10574
my ($index, $size, $type) = unpack($deffld_template, substr($$buffer, $i, $deffld_length));
8151
3410
5515
my ($name, $tname, %attr, );
8152
8153
3410
100
7711
if (ref $msgtype eq 'HASH') {
8154
3319
7138
my $fldtype = $msgtype->{$index};
8155
8156
3319
100
6553
if (ref $fldtype eq 'HASH') {
8157
2620
12442
%attr = %$fldtype;
8158
2620
6037
($name, $tname) = @attr{qw(name type_name)};
8159
2620
4337
delete $attr{name};
8160
2620
4346
delete $attr{type_name};
8161
}
8162
}
8163
8164
3410
100
7336
$name = $self->undocumented_field_name($index, $size, $type, $i_string) if !defined $name;
8165
3410
8620
$desc{$index} = $name;
8166
3410
5095
$type &= $deffld_mask_type;
8167
8168
3410
7160
my $c = int($size / $size[$type] + 0.5);
8169
8170
3410
9382
$desc{'i_' . $name} = $i_array;
8171
3410
7535
$desc{'o_' . $name} = $i_string;
8172
3410
8344
$desc{'c_' . $name} = $c;
8173
3410
9422
$desc{'s_' . $name} = $size[$type];
8174
3410
100
9200
$desc{'a_' . $name} = \%attr if %attr;
8175
3410
100
7241
$desc{'t_' . $name} = $tname if defined $tname;
8176
3410
8036
$desc{'T_' . $name} = $type;
8177
3410
9453
$desc{'N_' . $name} = $index;
8178
3410
9079
$desc{'I_' . $name} = $invalid[$type];
8179
8180
3410
9459
$self->add_endian_converter($endian, $type, $c, $i_string, \@cvt);
8181
8182
3410
5183
$i_array += $c;
8183
3410
4728
$i_string += $size;
8184
3410
6944
$desc{template} .= ' ' . $template[$type];
8185
8186
3410
50
6895
if ($packfactor[$type] > 1) {
8187
0
0
push @pi, $i_array_t, $c, $i_array;
8188
0
0
$c *= $packfactor[$type];
8189
}
8190
8191
3410
100
6378
$desc{template} .= $c if $c > 1;
8192
3410
9060
$i_array_t += $c;
8193
}
8194
8195
143
451
$desc{template_without_devdata} = $desc{template};
8196
143
299
$desc{devdata_first} = $i_array;
8197
143
360
$desc{devdata_nfields} = 0;
8198
8199
143
50
371
if ($record_header & $rechd_mask_devdata_message) {
8200
0
0
$self->offset($e);
8201
0
0
0
if ( $self->_buffer_needs_updating( $devdata_min_length ) ) {
8202
0
0
0
$self->fill_buffer or return undef
8203
}
8204
0
0
$i = $self->offset;
8205
0
0
($nfields) = unpack($devdata_min_template, substr($$buffer, $i, $devdata_min_length));
8206
8207
0
0
$self->offset($i + $devdata_min_length);
8208
0
0
$len = $nfields * $devdata_deffld_length;
8209
0
0
0
if ( $self->_buffer_needs_updating( $len ) ) {
8210
0
0
0
$self->fill_buffer or return undef
8211
}
8212
8213
0
0
my $devdata_by_index = $self->{devdata_by_index};
8214
0
0
my @emsg;
8215
8216
0
0
0
if (ref $devdata_by_index ne 'HASH') {
8217
0
0
push @emsg, 'No developer data id';
8218
0
0
$devdata_by_index = +{};
8219
}
8220
8221
0
0
for ($i = $self->offset, $e = $i + $len ; $i + $devdata_deffld_length <= $e ; $i += $devdata_deffld_length) {
8222
0
0
my ($fnum, $size, $index) = unpack($devdata_deffld_template, substr($$buffer, $i, $devdata_deffld_length));
8223
0
0
my $devdata = $devdata_by_index->{$index};
8224
0
0
my ($fdesc, $name, $type, %attr);
8225
8226
0
0
0
if (ref $devdata eq 'HASH') {
8227
0
0
my $fdesc_by_num = $devdata->{field_desc_by_num};
8228
8229
0
0
0
if (ref $fdesc_by_num eq 'HASH') {
8230
0
0
$fdesc = $fdesc_by_num->{$fnum};
8231
} else {
8232
0
0
push @emsg, "No field description message for developer data with index $index";
8233
}
8234
} else {
8235
0
0
push @emsg, "No developer data id with index $index";
8236
}
8237
8238
0
0
0
if (ref $fdesc eq 'HASH') {
8239
0
0
%attr = %$fdesc;
8240
0
0
($type, $name) = @attr{qw(_type _name)};
8241
} else {
8242
0
0
push @emsg, "No field with number $fnum for developer data with index $index";
8243
0
0
$type = FIT_UINT8;
8244
}
8245
8246
0
0
0
$name = $self->undocumented_field_name($fnum, $size, $type, $i_string) if !defined $name;
8247
0
0
$name = "${index}_${fnum}_$name";
8248
8249
0
0
my $c = int($size / $size[$type] + 0.5);
8250
8251
0
0
$desc{'i_' . $name} = $i_array;
8252
0
0
$desc{'o_' . $name} = $i_string;
8253
0
0
$desc{'c_' . $name} = $c;
8254
0
0
$desc{'s_' . $name} = $size[$type];
8255
0
0
0
$desc{'a_' . $name} = \%attr if %attr;
8256
0
0
$desc{'T_' . $name} = $type;
8257
0
0
$desc{'N_' . $name} = $fnum;
8258
0
0
$desc{'I_' . $name} = $invalid[$type];
8259
8260
0
0
$self->add_endian_converter($endian, $type, $c, $i_string, \@cvt);
8261
8262
0
0
$i_array += $c;
8263
0
0
$i_string += $size;
8264
0
0
$desc{template} .= ' ' . $template[$type];
8265
8266
0
0
0
if ($packfactor[$type] > 1) {
8267
0
0
push @pi, $type, $i_array_t, $c, $i_array;
8268
0
0
$c *= $packfactor[$type];
8269
}
8270
8271
0
0
0
$desc{template} .= $c if $c > 1;
8272
0
0
$i_array_t += $c;
8273
}
8274
8275
0
0
$desc{devdata_nfields} = $nfields;
8276
0
0
0
$self->error(join(' / ', @emsg)) if (@emsg);
8277
}
8278
8279
143
50
370
$desc{endian_converter} = \@cvt if @cvt;
8280
143
50
309
$desc{packfilter_index} = \@pi if @pi;
8281
143
499
$desc{message_length} = $i_string;
8282
143
405
$desc{array_length} = $i_array;
8283
143
503
$self->offset($e);
8284
143
496
return 1
8285
}
8286
8287
sub endian_convert {
8288
0
0
0
0
my ($self, $cvt, $buffer, $i) = @_;
8289
0
0
my $j;
8290
8291
0
0
for ($j = 4 ; $j < @$cvt ; $j += 5) {
8292
0
0
my ($b, $size, $c) = @$cvt[$j - 2, $j - 1, $j];
8293
8294
0
0
for ($b += $i ; $c > 0 ; $b += $size, --$c) {
8295
0
0
my @v = unpack($cvt->[$j - 3], substr($$buffer, $b, $size));
8296
0
0
my ($k, $l);
8297
8298
0
0
for ($k = 0, $l = $#v ; $k < $l ; ++$k, --$l) {
8299
0
0
@v[$k, $l] = @v[$l, $k];
8300
}
8301
0
0
substr($$buffer, $b, $size) = pack($cvt->[$j - 4], @v);
8302
}
8303
}
8304
}
8305
8306
sub last_timestamp {
8307
233
233
0
518
my $self = shift;
8308
233
50
481
if (@_) {
8309
233
616
$self->{last_timestamp} = $_[0];
8310
} else {
8311
0
0
$self->{last_timestamp};
8312
}
8313
}
8314
8315
sub fetch_data_message {
8316
1272
1272
0
2577
my ($self, $desc) = @_;
8317
1272
2768
my $buffer = $self->buffer;
8318
8319
1272
100
3344
if ( $self->_buffer_needs_updating( $desc->{message_length} ) ) {
8320
5
50
34
$self->fill_buffer or return undef
8321
}
8322
1272
50
3487
$self->endian_convert($desc->{endian_converter}, $self->buffer, $self->offset) if ref $desc->{endian_converter} eq 'ARRAY';
8323
8324
1272
2540
my $i = $self->offset;
8325
# unpack('f'/'d', ...) unpacks to NaN
8326
1272
8920
my @v = unpack($desc->{template}, substr($$buffer, $i, $desc->{message_length}));
8327
8328
1272
50
3711
if (ref $desc->{packfilter_index} eq 'ARRAY') {
8329
0
0
my $piv = $desc->{packfilter_index};
8330
0
0
my ($i, $j);
8331
0
0
my @v_t = @v;
8332
8333
0
0
@v = ($v_t[0]);
8334
8335
0
0
for ($i = 1, $j = 3 ; $j < @$piv ; $j += 4) {
8336
0
0
my ($type, $i_array_t, $c, $i_array) = @$piv[($j - 3) .. $j];
8337
0
0
my $delta = $packfactor[$type];
8338
8339
0
0
0
$i < $i_array_t and push @v, @v_t[$i .. ($i_array_t - 1)];
8340
0
0
$i = $i_array_t + $c * $delta;
8341
8342
0
0
for (; $i_array_t < $i ; $i_array_t += $delta) {
8343
0
0
push @v, $unpackfilter[$type]->(@v_t[$i_array_t .. ($i_array_t + $delta - 1)]);
8344
}
8345
}
8346
}
8347
8348
1272
3899
$self->offset($i + $desc->{message_length});
8349
8350
1272
2355
my $cb = $desc->{callback};
8351
8352
1272
2050
my $ret_val;
8353
1272
100
3366
if (ref $cb eq 'ARRAY') {
8354
749
50
1769
$v[0] & $rechd_mask_compressed_timestamp_header and push @v, $self->last_timestamp + ($v[0] & $rechd_mask_cth_timestamp);
8355
749
4062
$ret_val = $cb->[0]->($self, $desc, \@v, @$cb[1 .. $#$cb]);
8356
} else {
8357
523
864
$ret_val = 1;
8358
}
8359
1272
29112
return $ret_val
8360
}
8361
8362
sub pack_data_message {
8363
0
0
0
0
my ($self, $desc, $v) = @_;
8364
0
0
my $drop_devdata = $self->drop_developer_data;
8365
8366
0
0
0
0
if ($drop_devdata && ($desc->{message_name} eq 'developer_data_id' || $desc->{message_name} eq 'field_description')) {
0
8367
0
0
'';
8368
} else {
8369
0
0
my $rv = $v;
8370
8371
0
0
0
if (ref $desc->{packfilter_index} eq 'ARRAY') {
8372
0
0
my @v = ($v->[0]);
8373
0
0
my $piv = $desc->{packfilter_index};
8374
0
0
my ($i, $j);
8375
8376
0
0
for ($i = 1, $j = 3 ; $j < @$piv ; $j += 4) {
8377
0
0
my ($type, $i_array_t, $c, $i_array) = @$piv[($j - 3) .. $j];
8378
8379
0
0
0
$i < $i_array and push @v, @$v[$i .. ($i_array - 1)];
8380
0
0
$i = $i_array + $c;
8381
8382
0
0
for (; $i_array < $i ; ++$i_array) {
8383
0
0
push @v, $packfilter[$type]->($v->[$i_array]);
8384
}
8385
}
8386
0
0
$rv = \@v;
8387
}
8388
8389
0
0
0
if ($drop_devdata) {
8390
0
0
0
if ($desc->{devdata_first} > 0) {
8391
0
0
pack($desc->{template_without_devdata}, @$rv[0 .. ($desc->{devdata_first} - 1)]);
8392
} else {
8393
0
0
'';
8394
}
8395
} else {
8396
0
0
pack($desc->{template}, @$rv);
8397
}
8398
}
8399
}
8400
8401
=over 4
8402
8403
=item switched(I, I, I)
8404
8405
returns real data type attributes for a C's union like field.
8406
8407
=back
8408
8409
=cut
8410
8411
sub switched {
8412
68
68
1
967
my ($self, $desc, $v, $sw) = @_;
8413
68
139
my ($keyv, $key, $attr);
8414
8415
68
50
234
if (ref $sw->{_by} eq 'ARRAY') {
8416
0
0
$keyv = $sw->{_by};
8417
} else {
8418
68
307
$keyv = [$sw->{_by}];
8419
}
8420
8421
68
159
for $key (@$keyv) {
8422
68
150
my $i_name = 'i_' . $key;
8423
68
109
my $val;
8424
8425
68
100
66
587
if (defined $desc->{$i_name} && ($val = $v->[$desc->{$i_name}]) != $desc->{'I_' . $key}) {
8426
66
185
my $key_tn = $desc->{'t_' . $key};
8427
8428
66
50
159
if (defined $key_tn) {
8429
66
185
my $t_val = $self->named_type_value($key_tn, $val);
8430
8431
66
100
204
$val = $t_val if defined $t_val;
8432
}
8433
8434
66
100
209
if (ref $sw->{$val} eq 'HASH') {
8435
51
91
$attr = $sw->{$val};
8436
51
123
last;
8437
}
8438
}
8439
}
8440
68
179
$attr;
8441
}
8442
8443
sub _string_value {
8444
14
14
40
my ($v, $i, $n) = @_; # array of values, offset, count
8445
14
23
my $j;
8446
8447
14
41
for ($j = 0 ; $j < $n ; ++$j) {
8448
175
100
409
$v->[$i + $j] == 0 && last;
8449
}
8450
14
49
pack('C*', @{$v}[$i .. ($i + $j - 1)]);
14
123
8451
}
8452
8453
sub value_processed {
8454
4661
4661
0
16904
my ($self, $num, $attr) = @_;
8455
8456
4661
50
11202
if (ref $attr eq 'HASH') {
8457
4661
7192
my ($unit, $offset, $scale) = @{$attr}{qw(unit offset scale)};
4661
12527
8458
8459
4661
100
66
14404
$num /= $scale if defined $scale and $scale > 0;
8460
4661
100
9711
$num -= $offset if $offset;
8461
8462
4661
100
66
10023
if (defined $unit) {
100
8463
3525
8394
my $unit_tab = $self->unit_table($unit);
8464
8465
3525
100
8029
if (ref $unit_tab eq 'HASH') {
8466
1524
2452
my ($unit1, $offset1, $scale1) = @{$unit_tab}{qw(unit offset scale)};
1524
3872
8467
8468
1524
50
3351
if ($scale1 > 0) {
8469
1524
2825
$num /= $scale1;
8470
1524
2421
$scale += $scale1;
8471
}
8472
1524
50
2913
$num -= $offset1 if $offset1;
8473
1524
50
3673
$unit = $unit1 if defined $unit1
8474
}
8475
8476
3525
100
66
12273
if (defined $scale and $scale > 0) {
100
8477
3242
8272
my $below_pt = int(log($scale + 9) / log(10));
8478
8479
3242
100
6979
if ($self->without_unit) {
8480
2148
33717
sprintf("%.${below_pt}f", $num);
8481
} else {
8482
1094
11128
sprintf("%.${below_pt}f %s", $num, $unit);
8483
}
8484
} elsif ($self->without_unit) {
8485
22
98
$num;
8486
} else {
8487
261
1123
$num . " " . $unit;
8488
}
8489
} elsif (defined $scale and $scale > 0) {
8490
20
90
my $below_pt = int(log($scale + 9) / log(10));
8491
20
236
sprintf("%.${below_pt}f", $num);
8492
} else {
8493
1116
2840
$num;
8494
}
8495
} else {
8496
0
0
$num;
8497
}
8498
}
8499
8500
sub value_unprocessed {
8501
35
35
0
88
my ($self, $str, $attr) = @_;
8502
8503
35
50
98
if (ref $attr eq 'HASH') {
8504
35
56
my ($unit, $offset, $scale) = @{$attr}{qw(unit offset scale)};
35
104
8505
35
70
my $num = $str;
8506
8507
35
100
144
if (defined $unit) {
8508
30
83
my $unit_tab = $self->unit_table($unit);
8509
8510
30
100
83
if (ref $unit_tab eq 'HASH') {
8511
10
19
my ($unit1, $offset1, $scale1) = @{$unit_tab}{qw(unit offset scale)};
10
32
8512
8513
10
50
33
67
$scale += $scale1 if defined $scale1 and $scale1 > 0;
8514
10
50
92
$offset += $offset1 if $offset1;
8515
10
50
31
$unit = $unit1 if defined $unit1
8516
}
8517
8518
30
50
33
190
length($num) >= length($unit) && substr($num, -length($unit)) eq $unit
8519
and substr($num, -length($unit)) = '';
8520
}
8521
8522
35
50
94
$num += $offset if $offset;
8523
35
100
66
249
$num *= $scale if defined $scale and $scale > 0;
8524
35
98
$num;
8525
} else {
8526
0
0
$str;
8527
}
8528
}
8529
8530
=over 4
8531
8532
=item fields_list( $descriptor [, keep_unknown => $boole )
8533
8534
Given a data message descriptor (I<$descriptor>), returns the list of fields described in it. If C is set to true, unknown field names will also be listed.
8535
8536
=back
8537
8538
=cut
8539
8540
sub fields_list {
8541
44
44
1
289
my ($self, $desc) = (shift, shift);
8542
44
90
my %opts = @_;
8543
44
50
169
croak "argument to fields_list() does not look like a data descriptor hash" if ref $desc ne 'HASH';
8544
8545
44
82
my (@keys, %fields, @fields);
8546
8547
44
4063
@keys = grep /^i_/, keys %$desc;
8548
44
50
1140
@keys = grep !/^i_unknown/, @keys unless $opts{keep_unknown};
8549
8550
# %fields = %$desc{ @keys };
8551
44
112
for my $key (@keys) { # hash slices not supported in versions prior to 5.20
8552
834
1688
$fields{$key} = $desc->{$key};
8553
}
8554
8555
# sort for easy comparison with values aref passed to callbacks
8556
44
320
@fields = sort { $fields{$a} <=> $fields{$b} } keys %fields;
3050
5442
8557
44
997
map s/^i_//, @fields;
8558
return @fields
8559
44
563
}
8560
8561
=over 4
8562
8563
=item fields_defined( $descriptor, $values )
8564
8565
Given a data message descriptor (I<$descriptor>) and a corresponding data array reference of values (I<$values>), returns the list of fields whose value is defined. Unknow field names are never listed.
8566
8567
=back
8568
8569
=cut
8570
8571
sub fields_defined {
8572
22
22
1
21529
my ($self, $descriptor, $values) = @_;
8573
8574
22
89
my @fields = $self->fields_list( $descriptor );
8575
8576
22
73
my @defined;
8577
22
51
for my $field (@fields) {
8578
417
801
my $index = $descriptor->{ 'i_' . $field };
8579
417
100
1185
push @defined, $field if $values->[ $index ] != $descriptor->{'I_' . $field}
8580
}
8581
return @defined
8582
22
172
}
8583
8584
8585
=over 4
8586
8587
=item field_value( I<$field>, I<$descriptor>, I<$values> )
8588
8589
Returns the value of the field named I<$field> (a string).
8590
8591
The other arguments consist of the data message descriptor (I<$descriptor>, a hash reference) and the values fetched from a data message (I<$values>, an array reference). These are simply the references passed to data message callbacks by C, if any are registered, and are simply to be passed on to this method (please do not modifiy them).
8592
8593
For example, we can define and register a callback for C data messages and get the name of the manufacturer of the device that recorded the FIT file:
8594
8595
my $file_id_callback = sub {
8596
my ($self, $descriptor, $values) = @_;
8597
my $value = $self->field_value( 'manufacturer', $descriptor, $values );
8598
8599
print "The manufacturer is: ", $value, "\n"
8600
};
8601
8602
$fit->data_message_callback_by_name('file_id', $file_id_callback ) or die $fit->error;
8603
8604
1 while ( $fit->fetch );
8605
8606
=back
8607
8608
=cut
8609
8610
sub field_value {
8611
143
143
1
133748
my ($self, $field_name, $descriptor, $values_aref) = @_;
8612
8613
143
891
my @keys = map $_ . $field_name, qw( t_ a_ I_ );
8614
my ($type_name, $attr, $invalid, $value) =
8615
143
254
( @{$descriptor}{ @keys }, $values_aref->[ $descriptor->{'i_' . $field_name} ] );
143
845
8616
8617
143
100
492
if (defined $attr->{switch}) {
8618
14
56
my $t_attr = $self->switched($descriptor, $values_aref, $attr->{switch});
8619
14
100
45
if (ref $t_attr eq 'HASH') {
8620
13
22
$attr = $t_attr;
8621
$type_name = $attr->{type_name}
8622
13
37
}
8623
}
8624
8625
143
325
my $ret_val = $value;
8626
143
50
378
if ($value != $invalid) {
8627
143
100
364
if (defined $type_name) {
8628
74
226
$ret_val = $self->named_type_value($type_name, $value);
8629
74
100
406
return $ret_val if defined $ret_val
8630
}
8631
8632
79
50
271
if (ref $attr eq 'HASH') {
8633
79
224
$ret_val = $self->value_processed($value, $attr)
8634
}
8635
}
8636
79
332
return $ret_val
8637
}
8638
8639
=over 4
8640
8641
=item field_value_as_read( I<$field>, I<$descriptor>, I<$value> [, $type_name_or_aref ] )
8642
8643
Converts the value parsed and returned by C back to what it was when read from the FIT file and returns it.
8644
8645
This method is mostly for developers or if there is a particular need to inspect the data more closely, it should seldomly be used. Arguments are similar to C except that a single value I<$value> is passed instead of an array reference. That value corresponds to the value the former method has or would have returned.
8646
8647
As an example, we can obtain the actual value recorded in the FIT file for the manufacturer by adding these lines to the callback defined above:
8648
8649
my $as_read = $self->field_value_as_read( 'manufacturer', $descriptor, $value );
8650
print "The manufacturer's value as recorded in the FIT file is: ", $as_read, "\n"
8651
8652
The method will raise an exception if I<$value> would have been obtained by C via an internal call to C. In that case, the type name or the original array reference of values that was passed to the callback must be provided as the last argument. Otherwise, there is no way to guess what the value read from the file may have been.
8653
8654
=back
8655
8656
=cut
8657
8658
sub field_value_as_read {
8659
141
141
1
129540
my ($self, $field_name, $descriptor, $value, $optional_last_arg) = @_;
8660
8661
141
794
my @keys = map $_ . $field_name, qw( t_ a_ I_ );
8662
141
309
my ($type_name, $attr, $invalid) = ( @{$descriptor}{ @keys } );
141
525
8663
8664
141
100
540
if (defined $attr->{switch}) {
8665
8666
15
61
my $croak_msg = 'this field\'s value was derived from a call to switched(), please provide as the ';
8667
15
31
$croak_msg .= 'last argument the type name or the array reference containing the original values';
8668
15
50
41
croak $croak_msg unless defined $optional_last_arg;
8669
8670
15
100
49
if (ref $optional_last_arg eq 'ARRAY') {
8671
14
49
my $t_attr = $self->switched($descriptor, $optional_last_arg, $attr->{switch});
8672
14
100
44
if (ref $t_attr eq 'HASH') {
8673
13
23
$attr = $t_attr;
8674
$type_name = $attr->{type_name}
8675
13
28
}
8676
1
3
} else { $type_name = $optional_last_arg }
8677
}
8678
8679
141
234
my $ret_val = $value;
8680
141
100
873
if ($value !~ /^[-+]?\d+$/) {
8681
100
100
217
if (defined $type_name ) {
8682
65
196
my $ret_val = $self->named_type_value($type_name, $value);
8683
65
50
556
return $ret_val if defined $ret_val
8684
}
8685
8686
35
50
113
if (ref $attr eq 'HASH') {
8687
35
127
$ret_val = $self->value_unprocessed($value, $attr)
8688
}
8689
}
8690
76
335
return $ret_val
8691
}
8692
8693
=over 4
8694
8695
=item value_cooked(I, I, I, I)
8696
8697
This method is now deprecated and is no longer supported. Please use C instead.
8698
8699
converts I to a (hopefully) human readable form.
8700
8701
=back
8702
8703
=cut
8704
8705
sub value_cooked {
8706
3639
3639
1
8237
my ($self, $tname, $attr, $invalid, $val) = @_;
8707
8708
3639
100
7196
if ($val == $invalid) {
8709
781
1499
$val;
8710
} else {
8711
2858
100
5742
if (defined $tname) {
8712
393
1185
my $vname = $self->named_type_value($tname, $val);
8713
8714
393
100
1717
defined $vname && return $vname;
8715
}
8716
8717
2478
50
5566
if (ref $attr eq 'HASH') {
8718
2478
5509
$self->value_processed($val, $attr);
8719
} else {
8720
0
0
$val;
8721
}
8722
}
8723
}
8724
8725
=over 4
8726
8727
=item value_uncooked(I, I, I, I)
8728
8729
This method is now deprecated and is no longer supported. Please use C instead.
8730
8731
converts a human readable representation of a datum to an original form.
8732
8733
=back
8734
8735
=cut
8736
8737
sub value_uncooked {
8738
0
0
1
0
my ($self, $tname, $attr, $invalid, $val) = @_;
8739
8740
0
0
0
if ($val !~ /^[-+]?\d+$/) {
8741
0
0
0
if ($tname ne '') {
8742
0
0
my $vnum = $self->named_type_value($tname, $val);
8743
8744
0
0
0
defined $vnum && return $vnum;
8745
}
8746
8747
0
0
0
if (ref $attr eq 'HASH') {
8748
0
0
$self->value_unprocessed($val, $attr);
8749
} else {
8750
0
0
$val;
8751
}
8752
} else {
8753
0
0
$val;
8754
}
8755
}
8756
8757
sub seconds_to_hms {
8758
0
0
0
0
my ($self, $s) = @_;
8759
0
0
my $sign = 1;
8760
8761
0
0
0
if ($s < 0) {
8762
0
0
$sign = -1;
8763
0
0
$s = -$s;
8764
}
8765
8766
0
0
my $h = int($s / 3600);
8767
0
0
my $m = int(($s - $h * 3600) / 60);
8768
8769
0
0
$s -= $h * 3600 + $m * 60;
8770
8771
0
0
0
my $hms = sprintf('%s%uh%um%g', $sign < 0 ? '-' : '', $h, $m, $s);
8772
8773
0
0
0
$hms =~ s/\./s/ or $hms .= 's';
8774
0
0
$hms;
8775
}
8776
8777
sub drop_developer_data {
8778
3
3
0
7
my $self = shift;
8779
3
50
14
if (@_) {
8780
3
10
$self->{drop_developer_data} = $_[0];
8781
} else {
8782
0
0
$self->{drop_developer_data};
8783
}
8784
}
8785
8786
sub initialize {
8787
12
12
0
32
my $self = shift;
8788
12
31
my $buffer = '';
8789
8790
12
175
%$self = (
8791
'error' => undef,
8792
'file_read' => 0,
8793
'file_processed' => 0,
8794
'offset' => 0,
8795
'buffer' => \$buffer,
8796
'fh' => new FileHandle,
8797
'data_message_callback' => +{},
8798
'unit_table' => +{},
8799
'drop_developer_data' => 0,
8800
);
8801
8802
12
1036
$self->data_message_callback_by_name(developer_data_id => \&syscallback_devdata_id);
8803
12
103
$self->data_message_callback_by_name(field_description => \&syscallback_devdata_field_desc);
8804
12
28
$self;
8805
}
8806
8807
# undocumented (used by fitdump.pl is chained files)
8808
sub reset {
8809
0
0
0
0
my $self = shift;
8810
0
0
$self->clear_buffer;
8811
8812
0
0
%$self = map {($_ => $self->{$_})} qw(error buffer fh data_message_callback unit_table profile_version
0
0
8813
EOF use_gmtime numeric_date_time without_unit maybe_chained);
8814
8815
0
0
my $buffer = $self->buffer;
8816
0
0
$self->file_read(length($$buffer));
8817
0
0
$self->file_processed(0);
8818
0
0
$self;
8819
}
8820
8821
my @type_name = ();
8822
8823
$type_name[FIT_ENUM] = 'ENUM';
8824
$type_name[FIT_SINT8] = 'SINT8';
8825
$type_name[FIT_UINT8] = 'UINT8';
8826
$type_name[FIT_SINT16] = 'SINT16';
8827
$type_name[FIT_UINT16] = 'UINT16';
8828
$type_name[FIT_SINT32] = 'SINT32';
8829
$type_name[FIT_UINT32] = 'UINT32';
8830
$type_name[FIT_STRING] = 'STRING';
8831
$type_name[FIT_FLOAT32] = 'FLOAT32';
8832
$type_name[FIT_FLOAT64] = 'FLOAT64';
8833
$type_name[FIT_UINT8Z] = 'UINT8Z';
8834
$type_name[FIT_UINT16Z] = 'UINT16Z';
8835
$type_name[FIT_UINT32Z] = 'UINT32Z';
8836
$type_name[FIT_BYTE] = 'BYTE';
8837
8838
sub isnan {
8839
4151
4151
0
5511
my $ret_val;
8840
18
18
1358352
do { no warnings 'numeric'; $ret_val = !defined( $_[0] <=> 9**9**9 ) };
18
47
18
92275
4151
5460
4151
8395
8841
4151
9881
return $ret_val
8842
}
8843
8844
sub print_all_fields {
8845
243
243
0
965
my ($self, $desc, $v, %opt) = @_;
8846
243
632
my ($indent, $fh, $skip_invalid) = @opt{qw(indent fh skip_invalid)};
8847
8848
243
50
656
$fh = \*STDOUT if !defined $fh;
8849
243
50
661
$fh->print($indent, 'compressed_timestamp: ', $self->named_type_value('date_time', $v->[$#$v]), "\n") if $desc->{array_length} == $#$v;
8850
8851
243
5417
for my $i_name (sort {$desc->{$a} <=> $desc->{$b}} grep {/^i_/} keys %$desc) {
9978
16828
33079
57127
8852
3366
21805
my $name = $i_name;
8853
3366
11139
$name =~ s/^i_//;
8854
8855
3366
8114
my $attr = $desc->{'a_' . $name};
8856
3366
6135
my $tname = $desc->{'t_' . $name};
8857
3366
5137
my $pname = $name;
8858
8859
3366
100
8473
if (ref $attr->{switch} eq 'HASH') {
8860
32
116
my $t_attr = $self->switched($desc, $v, $attr->{switch});
8861
8862
32
100
66
if (ref $t_attr eq 'HASH') {
8863
17
28
$attr = $t_attr;
8864
17
27
$tname = $attr->{type_name};
8865
17
29
$pname = $attr->{name};
8866
}
8867
}
8868
8869
3366
5304
my $i = $desc->{$i_name};
8870
3366
6221
my $c = $desc->{'c_' . $name};
8871
3366
5882
my $type = $desc->{'T_' . $name};
8872
3366
6964
my $invalid = $desc->{'I_' . $name};
8873
3366
4768
my $j;
8874
8875
3366
7850
for ($j = 0 ; $j < $c ; ++$j) {
8876
3542
100
8143
isnan($v->[$i + $j]) && next;
8877
3541
100
9415
$v->[$i + $j] != $invalid && last;
8878
}
8879
8880
3366
50
66
11022
if ($j < $c || !$skip_invalid) {
8881
3366
100
7757
if (defined $tname) {
8882
370
100
100
2455
$self->last_timestamp($v->[$i]) if $type == FIT_UINT32 && $tname eq 'date_time' && $pname eq 'timestamp';
100
8883
}
8884
3366
50
15198
$fh->print($indent, $pname, ' (', $desc->{'N_' . $name}, '-', $c, '-', $type_name[$type] ne '' ? $type_name[$type] : $type);
8885
3366
100
26168
$fh->print(', original name: ', $name) if $name ne $pname;
8886
3366
100
7468
$fh->print(', INVALID') if $j >= $c;
8887
3366
12166
$fh->print('): ');
8888
8889
3366
100
19558
if ($type == FIT_STRING) {
8890
5
23
$fh->print("\"", _string_value($v, $i, $c), "\"\n");
8891
} else {
8892
3361
100
6789
$fh->print('{') if $c > 1;
8893
8894
3361
10458
my $pval = $self->value_cooked($tname, $attr, $invalid, $v->[$i]);
8895
8896
3361
10672
$fh->print($pval);
8897
3361
100
30258
$fh->print(' (', $v->[$i], ')') if $v->[$i] ne $pval;
8898
8899
3361
100
17284
if ($c > 1) {
8900
54
77
my ($j, $k);
8901
8902
54
148
for ($j = $i + 1, $k = $i + $c ; $j < $k ; ++$j) {
8903
174
324
$pval = $self->value_cooked($tname, $attr, $invalid, $v->[$j]);
8904
174
498
$fh->print(', ', $pval);
8905
174
50
1167
$fh->print(' (', $v->[$j], ')') if $v->[$j] ne $pval;
8906
}
8907
54
110
$fh->print('}');
8908
}
8909
3361
7027
$fh->print("\n");
8910
}
8911
}
8912
}
8913
243
4382
1;
8914
}
8915
8916
sub print_all_json {
8917
0
0
0
0
my ($self, $desc, $v, %opt) = @_;
8918
0
0
my ($indent, $fh, $skip_invalid) = @opt{qw(indent fh skip_invalid)};
8919
8920
0
0
my $out = 0;
8921
8922
0
0
0
$fh = \*STDOUT if !defined $fh;
8923
0
0
0
if ($desc->{array_length} == $#$v) {
8924
0
0
$fh->print($indent, '"compressed_timestamp": "', $self->named_type_value('date_time', $v->[$#$v]), '"');
8925
0
0
$out = $out + 1;
8926
}
8927
8928
0
0
for my $i_name (sort {$desc->{$a} <=> $desc->{$b}} grep {/^i_/} keys %$desc) {
0
0
0
0
8929
0
0
my $name = $i_name;
8930
0
0
$name =~ s/^i_//;
8931
8932
0
0
my $attr = $desc->{'a_' . $name};
8933
0
0
my $tname = $desc->{'t_' . $name};
8934
0
0
my $pname = $name;
8935
8936
0
0
0
if (ref $attr->{switch} eq 'HASH') {
8937
0
0
my $t_attr = $self->switched($desc, $v, $attr->{switch});
8938
8939
0
0
0
if (ref $t_attr eq 'HASH') {
8940
0
0
$attr = $t_attr;
8941
0
0
$tname = $attr->{type_name};
8942
0
0
$pname = $attr->{name};
8943
}
8944
}
8945
8946
0
0
my $i = $desc->{$i_name};
8947
0
0
my $c = $desc->{'c_' . $name};
8948
0
0
my $type = $desc->{'T_' . $name};
8949
0
0
my $invalid = $desc->{'I_' . $name};
8950
0
0
my $j;
8951
8952
0
0
for ($j = 0 ; $j < $c ; ++$j) {
8953
0
0
0
isnan($v->[$i + $j]) && next;
8954
0
0
0
$v->[$i + $j] != $invalid && last;
8955
}
8956
8957
0
0
0
0
if ($j < $c || !$skip_invalid) {
8958
0
0
0
0
$self->last_timestamp($v->[$i]) if $type == FIT_UINT32 && $tname eq 'date_time' && $pname eq 'timestamp';
0
8959
0
0
0
$fh->print(",\n") if $out;
8960
0
0
$fh->print($indent, '"', $pname, '": ');
8961
8962
0
0
0
if ($type == FIT_STRING) {
8963
0
0
$fh->print("\"", _string_value($v, $i, $c), "\"");
8964
} else {
8965
0
0
0
$fh->print('[') if $c > 1;
8966
8967
0
0
my $pval = $self->value_cooked($tname, $attr, $invalid, $v->[$i]);
8968
8969
0
0
0
if (looks_like_number($pval)) {
8970
0
0
$fh->print($pval);
8971
} else {
8972
0
0
$fh->print("\"$pval\"");
8973
}
8974
8975
0
0
0
if ($c > 1) {
8976
0
0
my ($j, $k);
8977
8978
0
0
for ($j = $i + 1, $k = $i + $c ; $j < $k ; ++$j) {
8979
0
0
$pval = $self->value_cooked($tname, $attr, $invalid, $v->[$j]);
8980
0
0
$fh->print(', ');
8981
0
0
0
if (looks_like_number($pval)) {
8982
0
0
$fh->print($pval);
8983
} else {
8984
0
0
$fh->print("\"$pval\"");
8985
}
8986
}
8987
8988
0
0
$fh->print(']');
8989
}
8990
}
8991
0
0
$out = $out + 1;
8992
}
8993
}
8994
0
0
1;
8995
}
8996
8997
=over 4
8998
8999
=item use_gmtime(I)
9000
9001
sets the flag which of GMT or local timezone is used for C type value conversion. Defaults to true.
9002
9003
=back
9004
9005
=cut
9006
9007
my $use_gmtime = 0;
9008
9009
sub use_gmtime {
9010
695
695
1
1290
my $self = shift;
9011
9012
695
100
1929
if (@_) {
50
9013
20
50
69
if (ref $self eq '') {
9014
0
0
$use_gmtime = $_[0];
9015
} else {
9016
20
56
$self->{use_gmtime} = $_[0];
9017
}
9018
} elsif (ref $self eq '') {
9019
0
0
$use_gmtime;
9020
} else {
9021
675
4250
$self->{use_gmtime};
9022
}
9023
}
9024
9025
=over 4
9026
9027
=item unit_table(I => I)
9028
9029
sets I for I.
9030
9031
=back
9032
9033
=cut
9034
9035
sub unit_table {
9036
3583
3583
1
5566
my $self = shift;
9037
3583
5203
my $unit = shift;
9038
9039
3583
100
6771
if (@_) {
9040
28
101
$self->{unit_table}->{$unit} = $_[0];
9041
} else {
9042
3555
9853
$self->{unit_table}->{$unit};
9043
}
9044
}
9045
9046
sub without_unit {
9047
3532
3532
0
5530
my $self = shift;
9048
3532
100
6143
if (@_) {
9049
7
28
$self->{without_unit} = $_[0];
9050
} else {
9051
3525
8141
$self->{without_unit};
9052
}
9053
}
9054
9055
=over 4
9056
9057
=item semicircles_to_degree(I)
9058
9059
=item mps_to_kph(I)
9060
9061
wrapper methods of C method. C defaults to true.
9062
9063
=back
9064
9065
=cut
9066
9067
sub semicircles_to_degree {
9068
20
20
1
67
my ($self, $on) = @_;
9069
20
50
130
$self->unit_table('semicircles' => $on ? +{'unit' => 'deg', 'scale' => 2 ** 31 / 180} : undef);
9070
}
9071
9072
sub mps_to_kph {
9073
8
8
1
32
my ($self, $on) = @_;
9074
8
100
43
$self->unit_table('m/s' => $on ? +{'unit' => 'km/h', 'scale' => 1 / 3.6} : undef);
9075
}
9076
9077
=over 4
9078
9079
=item close()
9080
9081
closes opened file handles.
9082
9083
=back
9084
9085
=cut
9086
9087
sub close {
9088
10
10
1
3429
my $self = shift;
9089
10
46
my $fh = $self->fh;
9090
10
50
110
$fh->close if $fh->opened;
9091
}
9092
9093
=over 4
9094
9095
=item profile_version_string()
9096
9097
Returns a string representation of the profile version used by the device or application that created the FIT file opened in the instance.
9098
9099
C<< fetch_header() >> must have been called at least once for this method to be able to return a value, will raise an exception otherwise.
9100
9101
=back
9102
9103
=head2 Functions
9104
9105
The following functions are provided. None are exported, they may be called as C<< Geo::FIT::message_name(20) >>, C<< Geo::FIT::field_name('device_info', 4) >> C<< Geo::FIT::field_number('device_info', 'product') >>, etc.
9106
9107
=over 4
9108
9109
=item message_name(I)
9110
9111
returns the message name for I or undef.
9112
9113
=item message_number(I)
9114
9115
returns the message number for I or undef.
9116
9117
=back
9118
9119
=cut
9120
9121
sub message_name {
9122
0
0
1
my $mspec = shift;
9123
0
0
my $msgtype = $mspec =~ /^\d+$/ ? $msgtype_by_num{$mspec} : $msgtype_by_name{$mspec};
9124
9125
0
0
if (ref $msgtype eq 'HASH') {
9126
0
$msgtype->{_name};
9127
} else {
9128
0
undef;
9129
}
9130
}
9131
9132
sub message_number {
9133
0
0
1
my $mspec = shift;
9134
0
0
my $msgtype = $mspec =~ /^\d+$/ ? $msgtype_by_num{$mspec} : $msgtype_by_name{$mspec};
9135
9136
0
0
if (ref $msgtype eq 'HASH') {
9137
0
$msgtype->{_number};
9138
} else {
9139
0
undef;
9140
}
9141
}
9142
9143
=over 4
9144
9145
=item field_name(I, I)
9146
9147
returns the field name for I in I or undef.
9148
9149
=item field_number(I, I)
9150
9151
returns the field index for I in I or undef.
9152
9153
=back
9154
9155
=cut
9156
9157
sub field_name {
9158
0
0
1
my ($mspec, $fspec) = @_;
9159
0
0
my $msgtype = $mspec =~ /^\d+$/ ? $msgtype_by_num{$mspec} : $msgtype_by_name{$mspec};
9160
9161
0
0
if (ref $msgtype eq 'HASH') {
9162
0
my $flddesc = $msgtype->{$fspec};
9163
ref $flddesc eq 'HASH'
9164
0
0
and return $flddesc->{name};
9165
}
9166
0
undef;
9167
}
9168
9169
sub field_number {
9170
0
0
1
my ($mspec, $fspec) = @_;
9171
0
0
my $msgtype = $mspec =~ /^\d+$/ ? $msgtype_by_num{$mspec} : $msgtype_by_name{$mspec};
9172
9173
0
0
if (ref $msgtype eq 'HASH') {
9174
0
my $flddesc = $msgtype->{$fspec};
9175
ref $flddesc eq 'HASH'
9176
0
0
and return $flddesc->{number};
9177
}
9178
0
undef;
9179
}
9180
9181
=head2 Constants
9182
9183
Following constants are exported: C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C.
9184
9185
Also exported are:
9186
9187
=over 4
9188
9189
=item FIT_BYTE
9190
9191
numbers representing base types of field values in data messages.
9192
9193
=item FIT_BASE_TYPE_MAX
9194
9195
the maximal number representing base types of field values in data messages.
9196
9197
=item FIT_HEADER_LENGTH
9198
9199
length of a .FIT file header.
9200
9201
=back
9202
9203
=head2 Data message descriptor
9204
9205
When C method meets a definition message, it creates a hash which includes various information about the corresponding data message. We call the hash a data message descriptor. It includes the following key value pairs.
9206
9207
=over 4
9208
9209
=item I => I
9210
9211
in a global .FIT profile.
9212
9213
=item C => I
9214
9215
necessarily.
9216
9217
=item C => I
9218
9219
necessarily.
9220
9221
=item C => I
9222
9223
only if the message is documented.
9224
9225
=item C => I
9226
9227
of a callback function and callback data, only if a C is registered.
9228
9229
=item C => I
9230
9231
of multi-octets data in this message, where 0 for littel-endian and 1 for big-endian.
9232
9233
=item C => I
9234
9235
used to convert the binary data to an array of Perl representations.
9236
9237
=item CI => I
9238
9239
of the value(s) of the field named I.
9240
9241
=item CI => I
9242
9243
of the value(s) of the field named I.
9244
9245
=item CI => I
9246
9247
of the field named I.
9248
9249
=item CI => I
9250
9251
of whole the field named I in binary data.
9252
9253
=item CI => I
9254
9255
of attributes of the field named I.
9256
9257
=item CI => I
9258
9259
only if the type of the value of the field named I has a name.
9260
9261
=item CI => I
9262
9263
representing base type of the value of the field named I.
9264
9265
=item CI => I
9266
9267
representing index of the filed named I in the global .FIT profile.
9268
9269
=item CI => I
9270
9271
representing the invalid value of the field named I, that is, if the value of the field in a binary datum equals to this number, the field must be treated as though it does not exist in the datum.
9272
9273
=item C => I
9274
9275
used for endian conversion.
9276
9277
=item C => I
9278
9279
in octets.
9280
9281
=item C => I
9282
9283
of Perl representations.
9284
9285
=back
9286
9287
=head2 Callback function
9288
9289
When C method meets a data message, it calls a I registered with C or C,
9290
in the form
9291
9292
=over 4
9293
9294
=item I-E(I, I, I, I, ...).
9295
9296
The return value of the function becomes the return value of C. It is expected to be C<1> on success, or C on failure status.
9297
9298
=back
9299
9300
=head2 Developer data
9301
9302
Fields in devloper data are given names of the form IC<_>IC<_>I, and related informations are included I in the same way as the fields defined in the global .FIT profile.
9303
9304
Each I is made from the value of C field in the corresponding I, after the following conversion rules:
9305
9306
=over 4
9307
9308
=item (1) Each sequence of space characters is converted to single C<_>.
9309
9310
=item (2) Each of remaining non-word-constituend characters is converted to C<_> + 2 column hex representation of C of the character + C<_>.
9311
9312
=back
9313
9314
=head2 64bit data
9315
9316
If your perl lacks 64bit integer support, you need the module C.
9317
9318
=head1 DEPENDENCIES
9319
9320
Nothing in particular so far.
9321
9322
=head1 SEE ALSO
9323
9324
L, L, L, L, L.
9325
9326
=head1 BUGS AND LIMITATIONS
9327
9328
No bugs have been reported.
9329
9330
Please report any bugs or feature requests to C, or through the web interface at L.
9331
9332
=head1 AUTHOR
9333
9334
Originally written by Kiyokazu Suto C<< suto@ks-and-ks.ne.jp >> with contributions by Matjaz Rihtar.
9335
9336
This version is maintained by Patrick Joly C<< >>.
9337
9338
Please visit the project page at: L.
9339
9340
=head1 VERSION
9341
9342
1.13
9343
9344
=head1 LICENSE AND COPYRIGHT
9345
9346
Copyright 2022, Patrick Joly C<< patjol@cpan.org >>. All rights reserved.
9347
9348
Copyright 2016-2022, Kiyokazu Suto C<< suto@ks-and-ks.ne.jp >>. All rights reserved.
9349
9350
This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See L.
9351
9352
=head1 DISCLAIMER OF WARRANTY
9353
9354
BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.
9355
9356
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
9357
9358
=cut
9359
9360
1;
9361