line
stmt
bran
cond
sub
pod
time
code
1
package Geo::FIT;
2
6
6
416153
use strict;
6
71
6
167
3
6
6
29
use warnings;
6
9
6
256
4
5
our $VERSION = '1.07';
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
$fit = Geo::FIT->new();
17
$fit->file( $fname )
18
$fit->open;
19
$fit->fetch_header;
20
$fit->fetch;
21
$fit->data_message_callback_by_name( $message name, \&callback_function [, \%callback_data, ... ] );
22
$fit->data_message_callback_by_num( $message number, \&callback_function [, \%callback_data, ... ] );
23
$fit->close;
24
25
=head1 DESCRIPTION
26
27
C is a Perl class to provide interfaces to decode Garmin FIT files (*.fit).
28
29
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).
30
31
=cut
32
33
6
6
30
use Carp qw/ croak /;
6
9
6
663
34
6
6
2881
use FileHandle;
6
60582
6
30
35
6
6
4958
use POSIX qw(BUFSIZ);
6
39151
6
32
36
6
6
11999
use Time::Local;
6
14409
6
379
37
6
6
50
use Scalar::Util qw(blessed looks_like_number);
6
11
6
631
38
39
my $uint64_invalid;
40
BEGIN {
41
6
6
20
eval { $uint64_invalid = unpack('Q', pack('a', -1)) };
6
42
42
6
50
25
unless (defined $uint64_invalid) {
43
6
7969
require Math::BigInt;
44
6
167575
import Math::BigInt
45
}
46
}
47
48
require Exporter;
49
our @ISA = qw(Exporter);
50
our @EXPORT = qw(
51
FIT_ENUM
52
FIT_SINT8
53
FIT_UINT8
54
FIT_SINT16
55
FIT_UINT16
56
FIT_SINT32
57
FIT_UINT32
58
FIT_SINT64
59
FIT_UINT64
60
FIT_STRING
61
FIT_FLOAT32
62
FIT_FLOAT64
63
FIT_UINT8Z
64
FIT_UINT16Z
65
FIT_UINT32Z
66
FIT_UINT64Z
67
FIT_BYTE
68
FIT_BASE_TYPE_MAX
69
FIT_HEADER_LENGTH
70
);
71
72
sub FIT_ENUM() {0;}
73
sub FIT_SINT8() {1;}
74
sub FIT_UINT8() {2;}
75
sub FIT_SINT16() {3;}
76
sub FIT_UINT16() {4;}
77
sub FIT_SINT32() {5;}
78
sub FIT_UINT32() {6;}
79
sub FIT_STRING() {7;}
80
sub FIT_FLOAT32() {8;}
81
sub FIT_FLOAT64() {9;}
82
sub FIT_UINT8Z() {10;}
83
sub FIT_UINT16Z() {11;}
84
sub FIT_UINT32Z() {12;}
85
sub FIT_BYTE() {13;}
86
sub FIT_SINT64() {14;}
87
sub FIT_UINT64() {15;}
88
sub FIT_UINT64Z() {16;}
89
sub FIT_BASE_TYPE_MAX() {FIT_UINT64Z;}
90
91
my $rechd_offset_compressed_timestamp_header = 7;
92
my $rechd_mask_compressed_timestamp_header = 1 << $rechd_offset_compressed_timestamp_header;
93
my $rechd_offset_cth_local_message_type = 5;
94
my $rechd_length_cth_local_message_type = 2;
95
my $rechd_mask_cth_local_message_type = ((1 << $rechd_length_cth_local_message_type) - 1) << $rechd_offset_cth_local_message_type;
96
my $rechd_length_cth_timestamp = $rechd_offset_cth_local_message_type;
97
my $rechd_mask_cth_timestamp = (1 << $rechd_length_cth_timestamp) - 1;
98
my $rechd_offset_definition_message = 6;
99
my $rechd_mask_definition_message = 1 << $rechd_offset_definition_message;
100
my $rechd_offset_devdata_message = 5;
101
my $rechd_mask_devdata_message = 1 << $rechd_offset_devdata_message;
102
my $rechd_length_local_message_type = 4;
103
my $rechd_mask_local_message_type = (1 << $rechd_length_local_message_type) - 1;
104
my $cthd_offset_local_message_type = 5;
105
my $cthd_length_local_message_type = 2;
106
my $cthd_mask_local_message_type = (1 << $cthd_length_local_message_type) - 1;
107
my $cthd_length_time_offset = 5;
108
my $cthd_mask_time_offset = (1 << $cthd_length_time_offset) - 1;
109
110
my $defmsg_min_template = 'C C C S C';
111
my $defmsg_min_length = length(pack($defmsg_min_template));
112
113
my $deffld_template = 'C C C';
114
my $deffld_length = length(pack($deffld_template));
115
my $deffld_mask_endian_p = 1 << 7;
116
my $deffld_mask_type = (1 << 5) - 1;
117
118
my $devdata_min_template = 'C';
119
my $devdata_min_length = length(pack($devdata_min_template));
120
my $devdata_deffld_template = 'C C C';
121
my $devdata_deffld_length = length(pack($deffld_template));
122
123
my @invalid = (0xFF) x ($deffld_mask_type + 1);
124
125
$invalid[FIT_SINT8] = 0x7F;
126
$invalid[FIT_SINT16] = 0x7FFF;
127
$invalid[FIT_UINT16] = 0xFFFF;
128
$invalid[FIT_SINT32] = 0x7FFFFFFF;
129
$invalid[FIT_UINT32] = 0xFFFFFFFF;
130
$invalid[FIT_STRING] = $invalid[FIT_UINT8Z] = $invalid[FIT_UINT16Z] = $invalid[FIT_UINT32Z] = $invalid[FIT_UINT64Z] = 0;
131
#$invalid[FIT_FLOAT32] = NaN;
132
#$invalid[FIT_FLOAT64] = NaN;
133
$invalid[FIT_FLOAT32] = unpack('f', pack('V', 0xFFFFFFFF));
134
$invalid[FIT_FLOAT64] = unpack('d', pack('V V', 0xFFFFFFFF, 0xFFFFFFFF));
135
136
my ($big_int_base32, $sint64_2c_mask, $sint64_2c_base, $sint64_2c_sign);
137
138
if (defined $uint64_invalid) {
139
$invalid[FIT_UINT64] = $uint64_invalid;
140
$invalid[FIT_SINT64] = eval '0x7FFFFFFFFFFFFFFF';
141
} else {
142
$invalid[FIT_UINT64] = Math::BigInt->new('0xFFFFFFFFFFFFFFFF');
143
$invalid[FIT_SINT64] = Math::BigInt->new('0x7FFFFFFFFFFFFFFF');
144
$big_int_base32 = Math::BigInt->new('0x100000000');
145
$sint64_2c_mask = Math::BigInt->new('0xFFFFFFFFFFFFFFFF');
146
$sint64_2c_base = Math::BigInt->new('0x10000000000000000');
147
$sint64_2c_sign = Math::BigInt->new('0x1000000000000000');
148
}
149
150
sub packfilter_uint64_big_endian {
151
0
0
0
0
my @res = $_[0]->bdiv($big_int_base32);
152
0
0
@res;
153
}
154
155
sub packfilter_uint64_little_endian {
156
0
0
0
0
my @res = $_[0]->bdiv($big_int_base32);
157
0
0
@res[1, 0];
158
}
159
160
my $my_endian = unpack('L', pack('N', 1)) == 1 ? 1 : 0;
161
162
*packfilter_uint64 = $my_endian ? \&packfilter_uint64_big_endian : \&packfilter_uint64_little_endian;
163
164
sub unpackfilter_uint64_big_endian {
165
0
0
0
0
my ($hi, $lo) = @_;
166
0
0
Math::BigInt->new($hi)->blsft(32)->badd($lo);
167
}
168
169
sub unpackfilter_uint64_little_endian {
170
0
0
0
0
&unpackfilter_uint64_big_endian(@_[1, 0]);
171
}
172
173
*unpackfilter_uint64 = $my_endian ? \&unpackfilter_uint64_big_endian : \&unpackfilter_uint64_little_endian;
174
175
sub packfilter_sint64_big_endian {
176
0
0
0
0
0
if ($_[0]->bcmp(0) < 0) {
177
0
0
&packfilter_uint64_big_endian($sint64_2c_mask->band($sint64_2c_base->badd($_[0])));
178
} else {
179
0
0
&packfilter_uint64_big_endian($_[0]);
180
}
181
}
182
183
sub packfilter_sint64_little_endian {
184
0
0
0
0
0
if ($_[0]->bcmp(0) < 0) {
185
0
0
&packfilter_uint64_little_endian($sint64_2c_mask->band($sint64_2c_base->badd($_[0])));
186
} else {
187
0
0
&packfilter_uint64_little_endian($_[0]);
188
}
189
}
190
191
*packfilter_sint64 = $my_endian ? \&packfilter_sint64_big_endian : \&packfilter_sint64_little_endian;
192
193
sub unpackfilter_sint64_big_endian {
194
0
0
0
0
my ($hi, $lo) = @_;
195
0
0
my $n = Math::BigInt->new($hi)->blsft(32)->badd($lo)->band($sint64_2c_mask);
196
197
0
0
0
if ($n->band($sint64_2c_sign)->bcmp(0) == 0) {
198
0
0
$n;
199
} else {
200
0
0
$n->bsub($sint64_2c_base);
201
}
202
}
203
204
sub unpackfilter_sint64_little_endian {
205
0
0
0
0
&unpackfilter_sint64_big_endian(@_[1, 0]);
206
}
207
208
*unpackfilter_sint64 = $my_endian ? \&unpackfilter_sint64_big_endian : \&unpackfilter_sint64_little_endian;
209
210
sub invalid {
211
0
0
1
0
my ($self, $type) = @_;
212
0
0
$invalid[$type & $deffld_mask_type];
213
}
214
215
my @size = (1) x ($deffld_mask_type + 1);
216
217
$size[FIT_SINT16] = $size[FIT_UINT16] = $size[FIT_UINT16Z] = 2;
218
$size[FIT_SINT32] = $size[FIT_UINT32] = $size[FIT_UINT32Z] = $size[FIT_FLOAT32] = 4;
219
$size[FIT_FLOAT64] = $size[FIT_SINT64] = $size[FIT_UINT64] = $size[FIT_UINT64Z] = 8;
220
221
my @template = ('C') x ($deffld_mask_type + 1);
222
my @packfactor = (1) x ($deffld_mask_type + 1);
223
my @packfilter = (undef) x ($deffld_mask_type + 1);
224
my @unpackfilter = (undef) x ($deffld_mask_type + 1);
225
226
$template[FIT_SINT8] = 'c';
227
$template[FIT_SINT16] = 's';
228
$template[FIT_UINT16] = $template[FIT_UINT16Z] = 'S';
229
$template[FIT_SINT32] = 'l';
230
$template[FIT_UINT32] = $template[FIT_UINT32Z] = 'L';
231
$template[FIT_FLOAT32] = 'f';
232
$template[FIT_FLOAT64] = 'd';
233
234
if (defined $uint64_invalid) {
235
$template[FIT_SINT64] = 'q';
236
$template[FIT_UINT64] = $template[FIT_UINT64Z] = 'Q';
237
} else {
238
$template[FIT_SINT64] = $template[FIT_UINT64] = $template[FIT_UINT64Z] = 'L';
239
$packfactor[FIT_SINT64] = $packfactor[FIT_UINT64] = $packfactor[FIT_UINT64Z] = 2;
240
$packfilter[FIT_SINT64] = \&packfilter_sint64;
241
$unpackfilter[FIT_SINT64] = \&unpackfilter_sint64;
242
$packfilter[FIT_UINT64] = $packfilter[FIT_UINT64Z] = \&packfilter_uint64;
243
$unpackfilter[FIT_UINT64] = $unpackfilter[FIT_UINT64Z] = \&unpackfilter_uint64;
244
}
245
246
my %named_type = (
247
'file' => +{
248
'_base_type' => FIT_ENUM,
249
'device' => 1,
250
'settings' => 2,
251
'sport' => 3,
252
'activity' => 4,
253
'workout' => 5,
254
'course' => 6,
255
'schedules' => 7,
256
'weight' => 9,
257
'totals' => 10,
258
'goals' => 11,
259
'blood_pressure' => 14,
260
'monitoring_a' => 15,
261
'activity_summary' => 20,
262
'monitoring_daily' => 28,
263
'monitoring_b' => 32,
264
'segment' => 34,
265
'segment_list' => 35,
266
'exd_configuration' => 40,
267
'mfg_range_min' => 0xF7,
268
'mfg_range_max' => 0xFE,
269
},
270
271
'mesg_num' => +{
272
'_base_type' => FIT_UINT16,
273
'file_id' => 0,
274
'capabilities' => 1,
275
'device_settings' => 2,
276
'user_profile' => 3,
277
'hrm_profile' => 4,
278
'sdm_profile' => 5,
279
'bike_profile' => 6,
280
'zones_target' => 7,
281
'hr_zone' => 8,
282
'power_zone' => 9,
283
'met_zone' => 10,
284
'sport' => 12,
285
'goal' => 15,
286
'session' => 18,
287
'lap' => 19,
288
'record' => 20,
289
'event' => 21,
290
'source' => 22, # undocumented
291
'device_info' => 23,
292
'workout' => 26,
293
'workout_step' => 27,
294
'schedule' => 28,
295
'location' => 29, # undocumented
296
'weight_scale' => 30,
297
'course' => 31,
298
'course_point' => 32,
299
'totals' => 33,
300
'activity' => 34,
301
'software' => 35,
302
'file_capabilities' => 37,
303
'mesg_capabilities' => 38,
304
'field_capabilities' => 39,
305
'file_creator' => 49,
306
'blood_pressure' => 51,
307
'speed_zone' => 53,
308
'monitoring' => 55,
309
'training_file' => 72,
310
'hrv' => 78,
311
'ant_rx' => 80,
312
'ant_tx' => 81,
313
'ant_channel_id' => 82,
314
'length' => 101,
315
'monitoring_info' => 103,
316
'battery' => 104, # undocumented
317
'pad' => 105,
318
'slave_device' => 106,
319
'connectivity' => 127,
320
'weather_conditions' => 128,
321
'weather_alert' => 129,
322
'cadence_zone' => 131,
323
'hr' => 132,
324
'segment_lap' => 142,
325
'memo_glob' => 145,
326
'sensor' => 147, # undocumented
327
'segment_id' => 148,
328
'segment_leaderboard_entry' => 149,
329
'segment_point' => 150,
330
'segment_file' => 151,
331
'workout_session' => 158,
332
'watchface_settings' => 159,
333
'gps_metadata' => 160,
334
'camera_event' => 161,
335
'timestamp_correlation' => 162,
336
'gyroscope_data' => 164,
337
'accelerometer_data' => 165,
338
'three_d_sensor_calibration' => 167,
339
'video_frame' => 169,
340
'obdii_data' => 174,
341
'nmea_sentence' => 177,
342
'aviation_attitude' => 178,
343
'video' => 184,
344
'video_title' => 185,
345
'video_description' => 186,
346
'video_clip' => 187,
347
'ohr_settings' => 188,
348
'exd_screen_configuration' => 200,
349
'exd_data_field_configuration' => 201,
350
'exd_data_concept_configuration' => 202,
351
'field_description' => 206,
352
'developer_data_id' => 207,
353
'magnetometer_data' => 208,
354
'barometer_data' => 209,
355
'one_d_sensor_calibration' => 210,
356
'time_in_zone' => 216,
357
'set' => 225,
358
'stress_level' => 227,
359
'dive_settings' => 258,
360
'dive_gas' => 259,
361
'dive_alarm' => 262,
362
'exercise_title' => 264,
363
'dive_summary' => 268,
364
'jump' => 285,
365
'split' => 312,
366
'climb_pro' => 317,
367
'tank_update' => 319,
368
'tank_summary' => 323,
369
'device_aux_battery_info' => 375,
370
'dive_apnea_alarm' => 393,
371
'mfg_range_min' => 0xFF00,
372
'mfg_range_max' => 0xFFFE,
373
},
374
375
'checksum' => +{
376
'_base_type' => FIT_UINT8,
377
'clear' => 0,
378
'ok' => 1,
379
},
380
381
'file_flags' => +{
382
'_base_type' => FIT_UINT8Z,
383
'_mask' => 1,
384
'read' => 0x02,
385
'write' => 0x04,
386
'erase' => 0x08,
387
},
388
389
'mesg_count' => +{
390
'_base_type' => FIT_ENUM,
391
'num_per_file' => 0,
392
'max_per_file' => 1,
393
'max_per_file_type' => 2,
394
},
395
396
'date_time' => +{
397
'_base_type' => FIT_UINT32,
398
'min' => 0x10000000,
399
'_min' => 0x10000000,
400
'_out_of_range' => 'seconds from device power on',
401
'_offset' => -timegm(0, 0, 0, 31, 11, 1989), # 1989-12-31 00:00:00 UTC
402
},
403
404
'local_date_time' => +{ # same as above, but in local time zone
405
'_base_type' => FIT_UINT32,
406
'min' => 0x10000000,
407
},
408
409
'message_index' => +{
410
'_base_type' => FIT_UINT16,
411
'_mask' => 1,
412
'selected' => 0x8000,
413
'reserved' => 0x7000,
414
'mask' => 0x0FFF,
415
},
416
417
'device_index' => +{ # dynamically created, as devices are added
418
'_base_type' => FIT_UINT8,
419
'creator' => 0, # creator of the file is always device index 0
420
'device1' => 1, # local, v6.00, garmin prod. edge520 (2067)
421
'device2' => 2, # local, v3.00, garmin prod. 1619
422
'heart_rate' => 3, # antplus
423
'speed' => 4, # antplus
424
'cadence' => 5, # antplus
425
'device6' => 6, # antplus power?
426
},
427
428
'gender' => +{
429
'_base_type' => FIT_ENUM,
430
'female' => 0,
431
'male' => 1,
432
},
433
434
'language' => +{
435
'_base_type' => FIT_ENUM,
436
'english' => 0,
437
'french' => 1,
438
'italian' => 2,
439
'german' => 3,
440
'spanish' => 4,
441
'croatian' => 5,
442
'czech' => 6,
443
'danish' => 7,
444
'dutch' => 8,
445
'finnish' => 9,
446
'greek' => 10,
447
'hungarian' => 11,
448
'norwegian' => 12,
449
'polish' => 13,
450
'portuguese' => 14,
451
'slovakian' => 15,
452
'slovenian' => 16,
453
'swedish' => 17,
454
'russian' => 18,
455
'turkish' => 19,
456
'latvian' => 20,
457
'ukrainian' => 21,
458
'arabic' => 22,
459
'farsi' => 23,
460
'bulgarian' => 24,
461
'romanian' => 25,
462
'chinese' => 26,
463
'japanese' => 27,
464
'korean' => 28,
465
'taiwanese' => 29,
466
'thai' => 30,
467
'hebrew' => 31,
468
'brazilian_portuguese' => 32,
469
'indonesian' => 33,
470
'malaysian' => 34,
471
'vietnamese' => 35,
472
'burmese' => 36,
473
'mongolian' => 37,
474
'custom' => 254,
475
},
476
477
'language_bits_0' => +{
478
'_base_type' => FIT_UINT8Z,
479
'english' => 0x01,
480
'french' => 0x02,
481
'italian' => 0x04,
482
'german' => 0x08,
483
'spanish' => 0x10,
484
'croatian' => 0x20,
485
'czech' => 0x40,
486
'danish' => 0x80,
487
},
488
489
'language_bits_1' => +{
490
'_base_type' => FIT_UINT8Z,
491
'dutch' => 0x01,
492
'finnish' => 0x02,
493
'greek' => 0x04,
494
'hungarian' => 0x08,
495
'norwegian' => 0x10,
496
'polish' => 0x20,
497
'portuguese' => 0x40,
498
'slovakian' => 0x80,
499
},
500
501
'language_bits_2' => +{
502
'_base_type' => FIT_UINT8Z,
503
'slovenian' => 0x01,
504
'swedish' => 0x02,
505
'russian' => 0x04,
506
'turkish' => 0x08,
507
'latvian' => 0x10,
508
'ukrainian' => 0x20,
509
'arabic' => 0x40,
510
'farsi' => 0x80,
511
},
512
513
'language_bits_3' => +{
514
'_base_type' => FIT_UINT8Z,
515
'bulgarian' => 0x01,
516
'romanian' => 0x02,
517
'chinese' => 0x04,
518
'japanese' => 0x08,
519
'korean' => 0x10,
520
'taiwanese' => 0x20,
521
'thai' => 0x40,
522
'hebrew' => 0x80,
523
},
524
525
'language_bits_4' => +{
526
'_base_type' => FIT_UINT8Z,
527
'brazilian_portuguese' => 0x01,
528
'indonesian' => 0x02,
529
'malaysian' => 0x04,
530
'vietnamese' => 0x08,
531
'burmese' => 0x10,
532
'mongolian' => 0x20,
533
},
534
535
'time_zone' => +{
536
'_base_type' => FIT_ENUM,
537
'almaty' => 0,
538
'bangkok' => 1,
539
'bombay' => 2,
540
'brasilia' => 3,
541
'cairo' => 4,
542
'cape_verde_is' => 5,
543
'darwin' => 6,
544
'eniwetok' => 7,
545
'fiji' => 8,
546
'hong_kong' => 9,
547
'islamabad' => 10,
548
'kabul' => 11,
549
'magadan' => 12,
550
'mid_atlantic' => 13,
551
'moscow' => 14,
552
'muscat' => 15,
553
'newfoundland' => 16,
554
'samoa' => 17,
555
'sydney' => 18,
556
'tehran' => 19,
557
'tokyo' => 20,
558
'us_alaska' => 21,
559
'us_atlantic' => 22,
560
'us_central' => 23,
561
'us_eastern' => 24,
562
'us_hawaii' => 25,
563
'us_mountain' => 26,
564
'us_pacific' => 27,
565
'other' => 28,
566
'auckland' => 29,
567
'kathmandu' => 30,
568
'europe_western_wet' => 31,
569
'europe_central_cet' => 32,
570
'europe_eastern_eet' => 33,
571
'jakarta' => 34,
572
'perth' => 35,
573
'adelaide' => 36,
574
'brisbane' => 37,
575
'tasmania' => 38,
576
'iceland' => 39,
577
'amsterdam' => 40,
578
'athens' => 41,
579
'barcelona' => 42,
580
'berlin' => 43,
581
'brussels' => 44,
582
'budapest' => 45,
583
'copenhagen' => 46,
584
'dublin' => 47,
585
'helsinki' => 48,
586
'lisbon' => 49,
587
'london' => 50,
588
'madrid' => 51,
589
'munich' => 52,
590
'oslo' => 53,
591
'paris' => 54,
592
'prague' => 55,
593
'reykjavik' => 56,
594
'rome' => 57,
595
'stockholm' => 58,
596
'vienna' => 59,
597
'warsaw' => 60,
598
'zurich' => 61,
599
'quebec' => 62,
600
'ontario' => 63,
601
'manitoba' => 64,
602
'saskatchewan' => 65,
603
'alberta' => 66,
604
'british_columbia' => 67,
605
'boise' => 68,
606
'boston' => 69,
607
'chicago' => 70,
608
'dallas' => 71,
609
'denver' => 72,
610
'kansas_city' => 73,
611
'las_vegas' => 74,
612
'los_angeles' => 75,
613
'miami' => 76,
614
'minneapolis' => 77,
615
'new_york' => 78,
616
'new_orleans' => 79,
617
'phoenix' => 80,
618
'santa_fe' => 81,
619
'seattle' => 82,
620
'washington_dc' => 83,
621
'us_arizona' => 84,
622
'chita' => 85,
623
'ekaterinburg' => 86,
624
'irkutsk' => 87,
625
'kaliningrad' => 88,
626
'krasnoyarsk' => 89,
627
'novosibirsk' => 90,
628
'petropavlovsk_kamchatskiy' => 91,
629
'samara' => 92,
630
'vladivostok' => 93,
631
'mexico_central' => 94,
632
'mexico_mountain' => 95,
633
'mexico_pacific' => 96,
634
'cape_town' => 97,
635
'winkhoek' => 98,
636
'lagos' => 99,
637
'riyahd' => 100,
638
'venezuela' => 101,
639
'australia_lh' => 102,
640
'santiago' => 103,
641
'manual' => 253,
642
'automatic' => 254,
643
},
644
645
'display_measure' => +{
646
'_base_type' => FIT_ENUM,
647
'metric' => 0,
648
'statute' => 1,
649
'nautical' => 2,
650
},
651
652
'display_heart' => +{
653
'_base_type' => FIT_ENUM,
654
'bpm' => 0,
655
'max' => 1,
656
'reserve' => 2,
657
},
658
659
'display_power' => +{
660
'_base_type' => FIT_ENUM,
661
'watts' => 0,
662
'percent_ftp' => 1,
663
},
664
665
'display_position' => +{
666
'_base_type' => FIT_ENUM,
667
'degree' => 0,
668
'degree_minute' => 1,
669
'degree_minute_second' => 2,
670
'austrian_grid' => 3,
671
'british_grid' => 4,
672
'dutch_grid' => 5,
673
'hungarian_grid' => 6,
674
'finnish_grid' => 7,
675
'german_grid' => 8,
676
'icelandic_grid' => 9,
677
'indonesian_equatorial' => 10,
678
'indonesian_irian' => 11,
679
'indonesian_southern' => 12,
680
'india_zone_0' => 13,
681
'india_zone_IA' => 14,
682
'india_zone_IB' => 15,
683
'india_zone_IIA' => 16,
684
'india_zone_IIB' => 17,
685
'india_zone_IIIA' => 18,
686
'india_zone_IIIB' => 19,
687
'india_zone_IVA' => 20,
688
'india_zone_IVB' => 21,
689
'irish_transverse' => 22,
690
'irish_grid' => 23,
691
'loran' => 24,
692
'maidenhead_grid' => 25,
693
'mgrs_grid' => 26,
694
'new_zealand_grid' => 27,
695
'new_zealand_transverse' => 28,
696
'qatar_grid' => 29,
697
'modified_swedish_grid' => 30,
698
'swedish_grid' => 31,
699
'south_african_grid' => 32,
700
'swiss_grid' => 33,
701
'taiwan_grid' => 34,
702
'united_states_grid' => 35,
703
'utm_ups_grid' => 36,
704
'west_malayan' => 37,
705
'borneo_rso' => 38,
706
'estonian_grid' => 39,
707
'latvian_grid' => 40,
708
'swedish_ref_99_grid' => 41,
709
},
710
711
'switch' => +{
712
'_base_type' => FIT_ENUM,
713
'off' => 0,
714
'on' => 1,
715
'auto' => 2,
716
},
717
718
'sport' => +{
719
'_base_type' => FIT_ENUM,
720
'generic' => 0,
721
'running' => 1,
722
'cycling' => 2,
723
'transition' => 3, # multisport transition
724
'fitness_equipment' => 4,
725
'swimming' => 5,
726
'basketball' => 6,
727
'soccer' => 7,
728
'tennis' => 8,
729
'american_football' => 9,
730
'training' => 10,
731
'walking' => 11,
732
'cross_country_skiing' => 12,
733
'alpine_skiing' => 13,
734
'snowboarding' => 14,
735
'rowing' => 15,
736
'mountaineering' => 16,
737
'hiking' => 17,
738
'multisport' => 18,
739
'paddling' => 19,
740
'flying' => 20,
741
'e_biking' => 21,
742
'motorcycling' => 22,
743
'boating' => 23,
744
'driving' => 24,
745
'golf' => 25,
746
'hang_gliding' => 26,
747
'horseback_riding' => 27,
748
'hunting' => 28,
749
'fishing' => 29,
750
'inline_skating' => 30,
751
'rock_climbing' => 31,
752
'sailing' => 32,
753
'ice_skating' => 33,
754
'sky_diving' => 34,
755
'snowshoeing' => 35,
756
'snowmobiling' => 36,
757
'stand_up_paddleboarding' => 37,
758
'surfing' => 38,
759
'wakeboarding' => 39,
760
'water_skiing' => 40,
761
'kayaking' => 41,
762
'rafting' => 42,
763
'windsurfing' => 43,
764
'kitesurfing' => 44,
765
'tactical' => 45,
766
'jumpmaster' => 46,
767
'boxing' => 47,
768
'floor_climbing' => 48,
769
'diving' => 53,
770
'hiit' => 62,
771
'racket' => 64,
772
'water_tubing' => 76,
773
'wakesurfing' => 77,
774
'all' => 254,
775
},
776
777
'sport_bits_0' => +{
778
'_base_type' => FIT_UINT8Z,
779
'generic' => 0x01,
780
'running' => 0x02,
781
'cycling' => 0x04,
782
'transition' => 0x08,
783
'fitness_equipment' => 0x10,
784
'swimming' => 0x20,
785
'basketball' => 0x40,
786
'soccer' => 0x80,
787
},
788
789
'sport_bits_1' => +{
790
'_base_type' => FIT_UINT8Z,
791
'tennis' => 0x01,
792
'american_football' => 0x02,
793
'training' => 0x04,
794
'walking' => 0x08,
795
'cross_country_skiing' => 0x10,
796
'alpine_skiing' => 0x20,
797
'snowboarding' => 0x40,
798
'rowing' => 0x80,
799
},
800
801
'sport_bits_2' => +{
802
'_base_type' => FIT_UINT8Z,
803
'mountaineering' => 0x01,
804
'hiking' => 0x02,
805
'multisport' => 0x04,
806
'paddling' => 0x08,
807
'flying' => 0x10,
808
'e_biking' => 0x20,
809
'motorcycling' => 0x40,
810
'boating' => 0x80,
811
},
812
813
'sport_bits_3' => +{
814
'_base_type' => FIT_UINT8Z,
815
'driving' => 0x01,
816
'golf' => 0x02,
817
'hang_gliding' => 0x04,
818
'horseback_riding' => 0x08,
819
'hunting' => 0x10,
820
'fishing' => 0x20,
821
'inline_skating' => 0x40,
822
'rock_climbing' => 0x80,
823
},
824
825
'sport_bits_4' => +{
826
'_base_type' => FIT_UINT8Z,
827
'sailing' => 0x01,
828
'ice_skating' => 0x02,
829
'sky_diving' => 0x04,
830
'snowshoeing' => 0x08,
831
'snowmobiling' => 0x10,
832
'stand_up_paddleboarding' => 0x20,
833
'surfing' => 0x40,
834
'wakeboarding' => 0x80,
835
},
836
837
'sport_bits_5' => +{
838
'_base_type' => FIT_UINT8Z,
839
'water_skiing' => 0x01,
840
'kayaking' => 0x02,
841
'rafting' => 0x04,
842
'windsurfing' => 0x08,
843
'kitesurfing' => 0x10,
844
'tactical' => 0x20,
845
'jumpmaster' => 0x40,
846
'boxing' => 0x80,
847
},
848
849
'sport_bits_6' => +{
850
'_base_type' => FIT_UINT8Z,
851
'floor_climbing' => 0x01,
852
},
853
854
'sub_sport' => +{
855
'_base_type' => FIT_ENUM,
856
'generic' => 0,
857
'treadmill' => 1, # run/fitness equipment
858
'street' => 2, # run
859
'trail' => 3, # run
860
'track' => 4, # run
861
'spin' => 5, # cycling
862
'indoor_cycling' => 6, # cycling/fitness equipment
863
'road' => 7, # cycling
864
'mountain' => 8, # cycling
865
'downhill' => 9, # cycling
866
'recumbent' => 10, # cycling
867
'cyclocross' => 11, # cycling
868
'hand_cycling' => 12, # cycling
869
'track_cycling' => 13, # cycling
870
'indoor_rowing' => 14, # fitness equipment
871
'elliptical' => 15, # fitness equipment
872
'stair_climbing' => 16, # fitness equipment
873
'lap_swimming' => 17, # swimming
874
'open_water' => 18, # swimming
875
'flexibility_training' => 19, # training
876
'strength_training' => 20, # training
877
'warm_up' => 21, # tennis
878
'match' => 22, # tennis
879
'exercise' => 23, # tennis
880
'challenge' => 24,
881
'indoor_skiing' => 25, # fitness equipment
882
'cardio_training' => 26, # training
883
'indoor_walking' => 27, # walking/fitness equipment
884
'e_bike_fitness' => 28, # e-biking
885
'bmx' => 29, # cycling
886
'casual_walking' => 30, # walking
887
'speed_walking' => 31, # walking
888
'bike_to_run_transition' => 32, # transition
889
'run_to_bike_transition' => 33, # transition
890
'swim_to_bike_transition' => 34, # transition
891
'atv' => 35, # motorcycling
892
'motocross' => 36, # motorcycling
893
'backcountry' => 37, # alpine skiing/snowboarding
894
'resort' => 38, # alpine skiing/snowboarding
895
'rc_drone' => 39, # flying
896
'wingsuit' => 40, # flying
897
'whitewater' => 41, # kayaking/rafting
898
'skate_skiing' => 42, # cross country skiing
899
'yoga' => 43, # training
900
'pilates' => 44, # fitness equipment
901
'indoor_running' => 45, # run/fitness equipment
902
'gravel_cycling' => 46, # cycling
903
'e_bike_mountain' => 47, # cycling
904
'commuting' => 48, # cycling
905
'mixed_surface' => 49, # cycling
906
'navigate' => 50,
907
'track_me' => 51,
908
'map' => 52,
909
'single_gas_diving' => 53, # Diving
910
'multi_gas_diving' => 54, # Diving
911
'gauge_diving' => 55, # Diving
912
'apnea_diving' => 56, # Diving
913
'apnea_hunting' => 57, # Diving
914
'virtual_activity' => 58,
915
'obstacle' => 59, # Used for events where participants run, crawl through mud, climb over walls, etc.
916
'breathing' => 62,
917
'sail_race' => 65, # Sailing
918
'ultra' => 67, # Ultramarathon
919
'indoor_climbing' => 68, # Climbing
920
'bouldering' => 69, # Climbing
921
'hiit' => 70, # High Intensity Interval Training
922
'amrap' => 73, # HIIT
923
'emom' => 74, # HIIT
924
'tabata' => 75, # HIIT
925
'pickleball' => 84, # Racket
926
'padel' => 85, # Racket
927
'all' => 254,
928
},
929
930
'sport_event' => +{
931
'_base_type' => FIT_ENUM,
932
'uncategorized' => 0,
933
'geocaching' => 1,
934
'fitness' => 2,
935
'recreation' => 3,
936
'race' => 4,
937
'special_event' => 5,
938
'training' => 6,
939
'transportation' => 7,
940
'touring' => 8,
941
},
942
943
'activity' => +{
944
'_base_type' => FIT_ENUM,
945
'manual' => 0,
946
'auto_multi_sport' => 1,
947
},
948
949
'intensity' => +{
950
'_base_type' => FIT_ENUM,
951
'active' => 0,
952
'rest' => 1,
953
'warmup' => 2,
954
'cooldown' => 3,
955
},
956
957
'session_trigger' => +{
958
'_base_type' => FIT_ENUM,
959
'activity_end' => 0,
960
'manual' => 1,
961
'auto_multi_sport' => 2,
962
'fitness_equipment' => 3,
963
},
964
965
'autolap_trigger' => +{
966
'_base_type' => FIT_ENUM,
967
'time' => 0,
968
'distance' => 1,
969
'position_start' => 2,
970
'position_lap' => 3,
971
'position_waypoint' => 4,
972
'position_marked' => 5,
973
'off' => 6,
974
},
975
976
'lap_trigger' => +{
977
'_base_type' => FIT_ENUM,
978
'manual' => 0,
979
'time' => 1,
980
'distance' => 2,
981
'position_start' => 3,
982
'position_lap' => 4,
983
'position_waypoint' => 5,
984
'position_marked' => 6,
985
'session_end' => 7,
986
'fitness_equipment' => 8,
987
},
988
989
'time_mode' => +{
990
'_base_type' => FIT_ENUM,
991
'hour12' => 0,
992
'hour24' => 1,
993
'military' => 2,
994
'hour_12_with_seconds' => 3,
995
'hour_24_with_seconds' => 4,
996
'utc' => 5,
997
},
998
999
'backlight_mode' => +{
1000
'_base_type' => FIT_ENUM,
1001
'off' => 0,
1002
'manual' => 1,
1003
'key_and_messages' => 2,
1004
'auto_brightness' => 3,
1005
'smart_notifications' => 4,
1006
'key_and_messages_night' => 5,
1007
'key_and_messages_and_smart_notifications' => 6,
1008
},
1009
1010
'date_mode' => +{
1011
'_base_type' => FIT_ENUM,
1012
'day_month' => 0,
1013
'month_day' => 1,
1014
},
1015
1016
'backlight_timeout' => +{
1017
'_base_type' => FIT_UINT8,
1018
'infinite' => 0,
1019
},
1020
1021
'event' => +{
1022
'_base_type' => FIT_ENUM,
1023
'timer' => 0,
1024
'workout' => 3,
1025
'workout_step' => 4,
1026
'power_down' => 5,
1027
'power_up' => 6,
1028
'off_course' => 7,
1029
'session' => 8,
1030
'lap' => 9,
1031
'course_point' => 10,
1032
'battery' => 11,
1033
'virtual_partner_pace' => 12,
1034
'hr_high_alert' => 13,
1035
'hr_low_alert' => 14,
1036
'speed_high_alert' => 15,
1037
'speed_low_alert' => 16,
1038
'cad_high_alert' => 17,
1039
'cad_low_alert' => 18,
1040
'power_high_alert' => 19,
1041
'power_low_alert' => 20,
1042
'recovery_hr' => 21,
1043
'battery_low' => 22,
1044
'time_duration_alert' => 23,
1045
'distance_duration_alert' => 24,
1046
'calorie_duration_alert' => 25,
1047
'activity' => 26,
1048
'fitness_equipment' => 27,
1049
'length' => 28,
1050
'user_marker' => 32,
1051
'sport_point' => 33,
1052
'calibration' => 36,
1053
'front_gear_change' => 42,
1054
'rear_gear_change' => 43,
1055
'rider_position_change' => 44,
1056
'elev_high_alert' => 45,
1057
'elev_low_alert' => 46,
1058
'comm_timeout' => 47,
1059
'dive_alert' => 56, # marker
1060
'dive_gas_switched' => 57, # marker
1061
'tank_pressure_reserve' => 71, # marker
1062
'tank_pressure_critical' => 72, # marker
1063
'tank_lost' => 73, # marker
1064
'radar_threat_alert' => 75, # start/stop/marker
1065
'tank_battery_low' => 76, # marker
1066
'tank_pod_connected' => 81, # marker - tank pod has connected
1067
'tank_pod_disconnected' => 82, # marker - tank pod has lost connection
1068
},
1069
1070
'event_type' => +{
1071
'_base_type' => FIT_ENUM,
1072
'start' => 0,
1073
'stop' => 1,
1074
'consecutive_depreciated' => 2,
1075
'marker' => 3,
1076
'stop_all' => 4,
1077
'begin_depreciated' => 5,
1078
'end_depreciated' => 6,
1079
'end_all_depreciated' => 7,
1080
'stop_disable' => 8,
1081
'stop_disable_all' => 9,
1082
},
1083
1084
'timer_trigger' => +{
1085
'_base_type' => FIT_ENUM,
1086
'manual' => 0,
1087
'auto' => 1,
1088
'fitness_equipment' => 2,
1089
},
1090
1091
'fitness_equipment_state' => +{
1092
'_base_type' => FIT_ENUM,
1093
'ready' => 0,
1094
'in_use' => 1,
1095
'paused' => 2,
1096
'unknown' => 3,
1097
},
1098
1099
'tone' => +{
1100
'_base_type' => FIT_ENUM,
1101
'off' => 0,
1102
'tone' => 1,
1103
'vibrate' => 2,
1104
'tone_and_vibrate' => 3,
1105
},
1106
'autoscroll' => +{
1107
'_base_type' => FIT_ENUM,
1108
'none' => 0,
1109
'slow' => 1,
1110
'medium' => 2,
1111
'fast' => 3,
1112
},
1113
1114
'activity_class' => +{
1115
'_base_type' => FIT_ENUM,
1116
'_mask' => 1,
1117
'level' => 0x7f,
1118
'level_max' => 100,
1119
'athlete' => 0x80,
1120
},
1121
1122
'hr_zone_calc' => +{
1123
'_base_type' => FIT_ENUM,
1124
'custom' => 0,
1125
'percent_max_hr' => 1,
1126
'percent_hrr' => 2,
1127
'percent_lthr' => 3,
1128
},
1129
1130
'pwr_zone_calc' => +{
1131
'_base_type' => FIT_ENUM,
1132
'custom' => 0,
1133
'percent_ftp' => 1,
1134
},
1135
1136
'wkt_step_duration' => +{
1137
'_base_type' => FIT_ENUM,
1138
'time' => 0,
1139
'distance' => 1,
1140
'hr_less_than' => 2,
1141
'hr_greater_than' => 3,
1142
'calories' => 4,
1143
'open' => 5,
1144
'repeat_until_steps_cmplt' => 6,
1145
'repeat_until_time' => 7,
1146
'repeat_until_distance' => 8,
1147
'repeat_until_calories' => 9,
1148
'repeat_until_hr_less_than' => 10,
1149
'repeat_until_hr_greater_than' => 11,
1150
'repeat_until_power_less_than' => 12,
1151
'repeat_until_power_greater_than' => 13,
1152
'power_less_than' => 14,
1153
'power_greater_than' => 15,
1154
'training_peaks_tss' => 16,
1155
'repeat_until_power_last_lap_less_than' => 17,
1156
'repeat_until_max_power_last_lap_less_than' => 18,
1157
'power_3s_less_than' => 19,
1158
'power_10s_less_than' => 20,
1159
'power_30s_less_than' => 21,
1160
'power_3s_greater_than' => 22,
1161
'power_10s_greater_than' => 23,
1162
'power_30s_greater_than' => 24,
1163
'power_lap_less_than' => 25,
1164
'power_lap_greater_than' => 26,
1165
'repeat_until_training_peaks_tss' => 27,
1166
'repetition_time' => 28,
1167
'reps' => 29,
1168
'time_only' => 31,
1169
},
1170
1171
'wkt_step_target' => +{
1172
'_base_type' => FIT_ENUM,
1173
'speed' => 0,
1174
'heart_rate' => 1,
1175
'open' => 2,
1176
'cadence' => 3,
1177
'power' => 4,
1178
'grade' => 5,
1179
'resistance' => 6,
1180
'power_3s' => 7,
1181
'power_10s' => 8,
1182
'power_30s' => 9,
1183
'power_lap' => 10,
1184
'swim_stroke' => 11,
1185
'speed_lap' => 12,
1186
'heart_rate_lap' => 13,
1187
},
1188
1189
'goal' => +{
1190
'_base_type' => FIT_ENUM,
1191
'time' => 0,
1192
'distance' => 1,
1193
'calories' => 2,
1194
'frequency' => 3,
1195
'steps' => 4,
1196
'ascent' => 5,
1197
'active_minutes' => 6,
1198
},
1199
1200
'goal_recurrence' => +{
1201
'_base_type' => FIT_ENUM,
1202
'off' => 0,
1203
'daily' => 1,
1204
'weekly' => 2,
1205
'monthly' => 3,
1206
'yearly' => 4,
1207
'custom' => 5,
1208
},
1209
1210
'goal_source' => +{
1211
'_base_type' => FIT_ENUM,
1212
'auto' => 0,
1213
'community' => 1,
1214
'user' => 2,
1215
},
1216
1217
'schedule' => +{
1218
'_base_type' => FIT_ENUM,
1219
'workout' => 0,
1220
'course' => 1,
1221
},
1222
1223
'course_point' => +{
1224
'_base_type' => FIT_ENUM,
1225
'generic' => 0,
1226
'summit' => 1,
1227
'valley' => 2,
1228
'water' => 3,
1229
'food' => 4,
1230
'danger' => 5,
1231
'left' => 6,
1232
'right' => 7,
1233
'straight' => 8,
1234
'first_aid' => 9,
1235
'fourth_category' => 10,
1236
'third_category' => 11,
1237
'second_category' => 12,
1238
'first_category' => 13,
1239
'hors_category' => 14,
1240
'sprint' => 15,
1241
'left_fork' => 16,
1242
'right_fork' => 17,
1243
'middle_fork' => 18,
1244
'slight_left' => 19,
1245
'sharp_left' => 20,
1246
'slight_right' => 21,
1247
'sharp_right' => 22,
1248
'u_turn' => 23,
1249
'segment_start' => 24,
1250
'segment_end' => 25,
1251
},
1252
1253
'manufacturer' => +{
1254
'_base_type' => FIT_UINT16,
1255
'garmin' => 1,
1256
'garmin_fr405_antfs' => 2,
1257
'zephyr' => 3,
1258
'dayton' => 4,
1259
'idt' => 5,
1260
'srm' => 6,
1261
'quarq' => 7,
1262
'ibike' => 8,
1263
'saris' => 9,
1264
'spark_hk' => 10,
1265
'tanita' => 11,
1266
'echowell' => 12,
1267
'dynastream_oem' => 13,
1268
'nautilus' => 14,
1269
'dynastream' => 15,
1270
'timex' => 16,
1271
'metrigear' => 17,
1272
'xelic' => 18,
1273
'beurer' => 19,
1274
'cardiosport' => 20,
1275
'a_and_d' => 21,
1276
'hmm' => 22,
1277
'suunto' => 23,
1278
'thita_elektronik' => 24,
1279
'gpulse' => 25,
1280
'clean_mobile' => 26,
1281
'pedal_brain' => 27,
1282
'peaksware' => 28,
1283
'saxonar' => 29,
1284
'lemond_fitness' => 30,
1285
'dexcom' => 31,
1286
'wahoo_fitness' => 32,
1287
'octane_fitness' => 33,
1288
'archinoetics' => 34,
1289
'the_hurt_box' => 35,
1290
'citizen_systems' => 36,
1291
'magellan' => 37,
1292
'osynce' => 38,
1293
'holux' => 39,
1294
'concept2' => 40,
1295
'one_giant_leap' => 42,
1296
'ace_sensor' => 43,
1297
'brim_brothers' => 44,
1298
'xplova' => 45,
1299
'perception_digital' => 46,
1300
'bf1systems' => 47,
1301
'pioneer' => 48,
1302
'spantec' => 49,
1303
'metalogics' => 50,
1304
'4iiiis' => 51,
1305
'seiko_epson' => 52,
1306
'seiko_epson_oem' => 53,
1307
'ifor_powell' => 54,
1308
'maxwell_guider' => 55,
1309
'star_trac' => 56,
1310
'breakaway' => 57,
1311
'alatech_technology_ltd' => 58,
1312
'mio_technology_europe' => 59,
1313
'rotor' => 60,
1314
'geonaute' => 61,
1315
'id_bike' => 62,
1316
'specialized' => 63,
1317
'wtek' => 64,
1318
'physical_enterprises' => 65,
1319
'north_pole_engineering' => 66,
1320
'bkool' => 67,
1321
'cateye' => 68,
1322
'stages_cycling' => 69,
1323
'sigmasport' => 70,
1324
'tomtom' => 71,
1325
'peripedal' => 72,
1326
'wattbike' => 73,
1327
'moxy' => 76,
1328
'ciclosport' => 77,
1329
'powerbahn' => 78,
1330
'acorn_projects_aps' => 79,
1331
'lifebeam' => 80,
1332
'bontrager' => 81,
1333
'wellgo' => 82,
1334
'scosche' => 83,
1335
'magura' => 84,
1336
'woodway' => 85,
1337
'elite' => 86,
1338
'nielsen_kellerman' => 87,
1339
'dk_city' => 88,
1340
'tacx' => 89,
1341
'direction_technology' => 90,
1342
'magtonic' => 91,
1343
'1partcarbon' => 92,
1344
'inside_ride_technologies' => 93,
1345
'sound_of_motion' => 94,
1346
'stryd' => 95,
1347
'icg' => 96,
1348
'mipulse' => 97,
1349
'bsx_athletics' => 98,
1350
'look' => 99,
1351
'campagnolo_srl' => 100,
1352
'body_bike_smart' => 101,
1353
'praxisworks' => 102,
1354
'limits_technology' => 103,
1355
'topaction_technology' => 104,
1356
'cosinuss' => 105,
1357
'fitcare' => 106,
1358
'magene' => 107,
1359
'giant_manufacturing_co' => 108,
1360
'tigrasport' => 109,
1361
'salutron' => 110,
1362
'technogym' => 111,
1363
'bryton_sensors' => 112,
1364
'latitude_limited' => 113,
1365
'soaring_technology' => 114,
1366
'igpsport' => 115,
1367
'thinkrider' => 116,
1368
'gopher_sport' => 117,
1369
'waterrower' => 118,
1370
'orangetheory' => 119,
1371
'inpeak' => 120,
1372
'kinetic' => 121,
1373
'johnson_health_tech' => 122,
1374
'polar_electro' => 123,
1375
'seesense' => 124,
1376
'nci_technology' => 125,
1377
'iqsquare' => 126,
1378
'leomo' => 127,
1379
'ifit_com' => 128,
1380
'coros_byte' => 129,
1381
'versa_design' => 130,
1382
'chileaf' => 131,
1383
'cycplus' => 132,
1384
'gravaa_byte' => 133,
1385
'sigeyi' => 134,
1386
'coospo' => 135,
1387
'geoid' => 136,
1388
'bosch' => 137,
1389
'kyto' => 138,
1390
'kinetic_sports' => 139,
1391
'decathlon_byte' => 140,
1392
'tq_systems' => 141,
1393
'tag_heuer' => 142,
1394
'keiser_fitness' => 143,
1395
'zwift_byte' => 144,
1396
'porsche_ep' => 145,
1397
'development' => 255,
1398
'healthandlife' => 257,
1399
'lezyne' => 258,
1400
'scribe_labs' => 259,
1401
'zwift' => 260,
1402
'watteam' => 261,
1403
'recon' => 262,
1404
'favero_electronics' => 263,
1405
'dynovelo' => 264,
1406
'strava' => 265,
1407
'precor' => 266,
1408
'bryton' => 267,
1409
'sram' => 268,
1410
'navman' => 269,
1411
'cobi' => 270,
1412
'spivi' => 271,
1413
'mio_magellan' => 272,
1414
'evesports' => 273,
1415
'sensitivus_gauge' => 274,
1416
'podoon' => 275,
1417
'life_time_fitness' => 276,
1418
'falco_e_motors' => 277,
1419
'minoura' => 278,
1420
'cycliq' => 279,
1421
'luxottica' => 280,
1422
'trainer_road' => 281,
1423
'the_sufferfest' => 282,
1424
'fullspeedahead' => 283,
1425
'virtualtraining' => 284,
1426
'feedbacksports' => 285,
1427
'omata' => 286,
1428
'vdo' => 287,
1429
'magneticdays' => 288,
1430
'hammerhead' => 289,
1431
'kinetic_by_kurt' => 290,
1432
'shapelog' => 291,
1433
'dabuziduo' => 292,
1434
'jetblack' => 293,
1435
'coros' => 294,
1436
'virtugo' => 295,
1437
'velosense' => 296,
1438
'cycligentinc' => 297,
1439
'trailforks' => 298,
1440
'mahle_ebikemotion' => 299,
1441
'nurvv' => 300,
1442
'microprogram' => 301,
1443
'zone5cloud' => 302,
1444
'greenteg' => 303,
1445
'yamaha_motors' => 304,
1446
'whoop' => 305,
1447
'gravaa' => 306,
1448
'onelap' => 307,
1449
'monark_exercise' => 308,
1450
'form' => 309,
1451
'decathlon' => 310,
1452
'syncros' => 311,
1453
'heatup' => 312,
1454
'cannondale' => 313,
1455
'true_fitness' => 314,
1456
'RGT_cycling' => 315,
1457
'vasa' => 316,
1458
'race_republic' => 317,
1459
'fazua' => 318,
1460
'oreka_training' => 319,
1461
'lsec' => 320, # Lishun Electric & Communication
1462
'lululemon_studio' => 321,
1463
'shanyue' => 322,
1464
'actigraphcorp' => 5759,
1465
},
1466
1467
'garmin_product' => +{
1468
'_base_type' => FIT_UINT16,
1469
'hrm1' => 1,
1470
'axh01' => 2, # AXH01 HRM chipset
1471
'axb01' => 3,
1472
'axb02' => 4,
1473
'hrm2ss' => 5,
1474
'dsi_alf02' => 6,
1475
'hrm3ss' => 7,
1476
'hrm_run_single_byte_product_id' => 8, # hrm_run model for HRM ANT+ messaging
1477
'bsm' => 9, # BSM model for ANT+ messaging
1478
'bcm' => 10, # BCM model for ANT+ messaging
1479
'axs01' => 11, # AXS01 HRM Bike Chipset model for ANT+ messaging
1480
'hrm_tri_single_byte_product_id' => 12, # hrm_tri model for HRM ANT+ messaging
1481
'hrm4_run_single_byte_product_id' => 13, # hrm4 run model for HRM ANT+ messaging
1482
'fr225_single_byte_product_id' => 14, # fr225 model for HRM ANT+ messaging
1483
'gen3_bsm_single_byte_product_id' => 15, # gen3_bsm model for Bike Speed ANT+ messaging
1484
'gen3_bcm_single_byte_product_id' => 16, # gen3_bcm model for Bike Cadence ANT+ messaging
1485
'OHR' => 255, # Garmin Wearable Optical Heart Rate Sensor for ANT+ HR Profile Broadcasting
1486
'fr301_china' => 473,
1487
'fr301_japan' => 474,
1488
'fr301_korea' => 475,
1489
'fr301_taiwan' => 494,
1490
'fr405' => 717, # Forerunner 405
1491
'fr50' => 782, # Forerunner 50
1492
'fr405_japan' => 987,
1493
'fr60' => 988, # Forerunner 60
1494
'dsi_alf01' => 1011,
1495
'fr310xt' => 1018, # Forerunner 310
1496
'edge500' => 1036,
1497
'fr110' => 1124, # Forerunner 110
1498
'edge800' => 1169,
1499
'edge500_taiwan' => 1199,
1500
'edge500_japan' => 1213,
1501
'chirp' => 1253,
1502
'fr110_japan' => 1274,
1503
'edge200' => 1325,
1504
'fr910xt' => 1328,
1505
'edge800_taiwan' => 1333,
1506
'edge800_japan' => 1334,
1507
'alf04' => 1341,
1508
'fr610' => 1345,
1509
'fr210_japan' => 1360,
1510
'vector_ss' => 1380,
1511
'vector_cp' => 1381,
1512
'edge800_china' => 1386,
1513
'edge500_china' => 1387,
1514
'approach_g10' => 1405,
1515
'fr610_japan' => 1410,
1516
'edge500_korea' => 1422,
1517
'fr70' => 1436,
1518
'fr310xt_4t' => 1446,
1519
'amx' => 1461,
1520
'fr10' => 1482,
1521
'edge800_korea' => 1497,
1522
'swim' => 1499,
1523
'fr910xt_china' => 1537,
1524
'fenix' => 1551,
1525
'edge200_taiwan' => 1555,
1526
'edge510' => 1561,
1527
'edge810' => 1567,
1528
'tempe' => 1570,
1529
'fr910xt_japan' => 1600,
1530
'fr620' => 1623,
1531
'fr220' => 1632,
1532
'fr910xt_korea' => 1664,
1533
'fr10_japan' => 1688,
1534
'edge810_japan' => 1721,
1535
'virb_elite' => 1735,
1536
'edge_touring' => 1736, # Also Edge Touring Plus
1537
'edge510_japan' => 1742,
1538
'hrm_tri' => 1743, # Also HRM-Swim
1539
'hrm_run' => 1752,
1540
'fr920xt' => 1765,
1541
'edge510_asia' => 1821,
1542
'edge810_china' => 1822,
1543
'edge810_taiwan' => 1823,
1544
'edge1000' => 1836,
1545
'vivo_fit' => 1837,
1546
'virb_remote' => 1853,
1547
'vivo_ki' => 1885,
1548
'fr15' => 1903,
1549
'vivo_active' => 1907,
1550
'edge510_korea' => 1918,
1551
'fr620_japan' => 1928,
1552
'fr620_china' => 1929,
1553
'fr220_japan' => 1930,
1554
'fr220_china' => 1931,
1555
'approach_s6' => 1936,
1556
'vivo_smart' => 1956,
1557
'fenix2' => 1967,
1558
'epix' => 1988,
1559
'fenix3' => 2050,
1560
'edge1000_taiwan' => 2052,
1561
'edge1000_japan' => 2053,
1562
'fr15_japan' => 2061,
1563
'edge520' => 2067,
1564
'edge1000_china' => 2070,
1565
'fr620_russia' => 2072,
1566
'fr220_russia' => 2073,
1567
'vector_s' => 2079,
1568
'edge1000_korea' => 2100,
1569
'fr920xt_taiwan' => 2130,
1570
'fr920xt_china' => 2131,
1571
'fr920xt_japan' => 2132,
1572
'virbx' => 2134,
1573
'vivo_smart_apac' => 2135,
1574
'etrex_touch' => 2140,
1575
'edge25' => 2147,
1576
'fr25' => 2148,
1577
'vivo_fit2' => 2150,
1578
'fr225' => 2153,
1579
'fr630' => 2156,
1580
'fr230' => 2157,
1581
'fr735xt' => 2158,
1582
'vivo_active_apac' => 2160,
1583
'vector_2' => 2161,
1584
'vector_2s' => 2162,
1585
'virbxe' => 2172,
1586
'fr620_taiwan' => 2173,
1587
'fr220_taiwan' => 2174,
1588
'truswing' => 2175,
1589
'd2airvenu' => 2187,
1590
'fenix3_china' => 2188,
1591
'fenix3_twn' => 2189,
1592
'varia_headlight' => 2192,
1593
'varia_taillight_old' => 2193,
1594
'edge_explore_1000' => 2204,
1595
'fr225_asia' => 2219,
1596
'varia_radar_taillight' => 2225,
1597
'varia_radar_display' => 2226,
1598
'edge20' => 2238,
1599
'edge520_asia' => 2260,
1600
'edge520_japan' => 2261,
1601
'd2_bravo' => 2262,
1602
'approach_s20' => 2266,
1603
'vivo_smart2' => 2271,
1604
'edge1000_thai' => 2274,
1605
'varia_remote' => 2276,
1606
'edge25_asia' => 2288,
1607
'edge25_jpn' => 2289,
1608
'edge20_asia' => 2290,
1609
'approach_x40' => 2292,
1610
'fenix3_japan' => 2293,
1611
'vivo_smart_emea' => 2294,
1612
'fr630_asia' => 2310,
1613
'fr630_jpn' => 2311,
1614
'fr230_jpn' => 2313,
1615
'hrm4_run' => 2327,
1616
'epix_japan' => 2332,
1617
'vivo_active_hr' => 2337,
1618
'vivo_smart_gps_hr' => 2347,
1619
'vivo_smart_hr' => 2348,
1620
'vivo_smart_hr_asia' => 2361,
1621
'vivo_smart_gps_hr_asia' => 2362,
1622
'vivo_move' => 2368,
1623
'varia_taillight' => 2379,
1624
'fr235_asia' => 2396,
1625
'fr235_japan' => 2397,
1626
'varia_vision' => 2398,
1627
'vivo_fit3' => 2406,
1628
'fenix3_korea' => 2407,
1629
'fenix3_sea' => 2408,
1630
'fenix3_hr' => 2413,
1631
'virb_ultra_30' => 2417,
1632
'index_smart_scale' => 2429,
1633
'fr235' => 2431,
1634
'fenix3_chronos' => 2432,
1635
'oregon7xx' => 2441,
1636
'rino7xx' => 2444,
1637
'epix_korea' => 2457,
1638
'fenix3_hr_chn' => 2473,
1639
'fenix3_hr_twn' => 2474,
1640
'fenix3_hr_jpn' => 2475,
1641
'fenix3_hr_sea' => 2476,
1642
'fenix3_hr_kor' => 2477,
1643
'nautix' => 2496,
1644
'vivo_active_hr_apac' => 2497,
1645
'fr35' => 2503,
1646
'oregon7xx_ww' => 2512,
1647
'edge_820' => 2530,
1648
'edge_explore_820' => 2531,
1649
'fr735xt_apac' => 2533,
1650
'fr735xt_japan' => 2534,
1651
'fenix5s' => 2544,
1652
'd2_bravo_titanium' => 2547,
1653
'varia_ut800' => 2567, # Varia UT 800 SW
1654
'running_dynamics_pod' => 2593,
1655
'edge_820_china' => 2599,
1656
'edge_820_japan' => 2600,
1657
'fenix5x' => 2604,
1658
'vivo_fit_jr' => 2606,
1659
'vivo_smart3' => 2622,
1660
'vivo_sport' => 2623,
1661
'edge_820_taiwan' => 2628,
1662
'edge_820_korea' => 2629,
1663
'edge_820_sea' => 2630,
1664
'fr35_hebrew' => 2650,
1665
'approach_s60' => 2656,
1666
'fr35_apac' => 2667,
1667
'fr35_japan' => 2668,
1668
'fenix3_chronos_asia' => 2675,
1669
'virb_360' => 2687,
1670
'fr935' => 2691,
1671
'fenix5' => 2697,
1672
'vivoactive3' => 2700,
1673
'fr235_china_nfc' => 2733,
1674
'foretrex_601_701' => 2769,
1675
'vivo_move_hr' => 2772,
1676
'edge_1030' => 2713,
1677
'fr35_sea' => 2727,
1678
'vector_3' => 2787,
1679
'fenix5_asia' => 2796,
1680
'fenix5s_asia' => 2797,
1681
'fenix5x_asia' => 2798,
1682
'approach_z80' => 2806,
1683
'fr35_korea' => 2814,
1684
'd2charlie' => 2819,
1685
'vivo_smart3_apac' => 2831,
1686
'vivo_sport_apac' => 2832,
1687
'fr935_asia' => 2833,
1688
'descent' => 2859,
1689
'vivo_fit4' => 2878,
1690
'fr645' => 2886,
1691
'fr645m' => 2888,
1692
'fr30' => 2891,
1693
'fenix5s_plus' => 2900,
1694
'Edge_130' => 2909,
1695
'edge_1030_asia' => 2924,
1696
'vivosmart_4' => 2927,
1697
'vivo_move_hr_asia' => 2945,
1698
'approach_x10' => 2962,
1699
'fr30_asia' => 2977,
1700
'vivoactive3m_w' => 2988,
1701
'fr645_asia' => 3003,
1702
'fr645m_asia' => 3004,
1703
'edge_explore' => 3011,
1704
'gpsmap66' => 3028,
1705
'approach_s10' => 3049,
1706
'vivoactive3m_l' => 3066,
1707
'approach_g80' => 3085,
1708
'edge_130_asia' => 3092,
1709
'edge_1030_bontrager' => 3095,
1710
'fenix5_plus' => 3110,
1711
'fenix5x_plus' => 3111,
1712
'edge_520_plus' => 3112,
1713
'fr945' => 3113,
1714
'edge_530' => 3121,
1715
'edge_830' => 3122,
1716
'instinct_esports' => 3126,
1717
'fenix5s_plus_apac' => 3134,
1718
'fenix5x_plus_apac' => 3135,
1719
'edge_520_plus_apac' => 3142,
1720
'fr235l_asia' => 3144,
1721
'fr245_asia' => 3145,
1722
'vivo_active3m_apac' => 3163,
1723
'gen3_bsm' => 3192, # gen3 bike speed sensor
1724
'gen3_bcm' => 3193, # gen3 bike cadence sensor
1725
'vivo_smart4_asia' => 3218,
1726
'vivoactive4_small' => 3224,
1727
'vivoactive4_large' => 3225,
1728
'venu' => 3226,
1729
'marq_driver' => 3246,
1730
'marq_aviator' => 3247,
1731
'marq_captain' => 3248,
1732
'marq_commander' => 3249,
1733
'marq_expedition' => 3250,
1734
'marq_athlete' => 3251,
1735
'descent_mk2' => 3258,
1736
'gpsmap66i' => 3284,
1737
'fenix6S_sport' => 3287,
1738
'fenix6S' => 3288,
1739
'fenix6_sport' => 3289,
1740
'fenix6' => 3290,
1741
'fenix6x' => 3291,
1742
'hrm_dual' => 3299, # HRM-Dual
1743
'hrm_pro' => 3300, # HRM-Pro
1744
'vivo_move3_premium' => 3308,
1745
'approach_s40' => 3314,
1746
'fr245m_asia' => 3321,
1747
'edge_530_apac' => 3349,
1748
'edge_830_apac' => 3350,
1749
'vivo_move3' => 3378,
1750
'vivo_active4_small_asia' => 3387,
1751
'vivo_active4_large_asia' => 3388,
1752
'vivo_active4_oled_asia' => 3389,
1753
'swim2' => 3405,
1754
'marq_driver_asia' => 3420,
1755
'marq_aviator_asia' => 3421,
1756
'vivo_move3_asia' => 3422,
1757
'fr945_asia' => 3441,
1758
'vivo_active3t_chn' => 3446,
1759
'marq_captain_asia' => 3448,
1760
'marq_commander_asia' => 3449,
1761
'marq_expedition_asia' => 3450,
1762
'marq_athlete_asia' => 3451,
1763
'instinct_solar' => 3466,
1764
'fr45_asia' => 3469,
1765
'vivoactive3_daimler' => 3473,
1766
'legacy_rey' => 3498,
1767
'legacy_darth_vader' => 3499,
1768
'legacy_captain_marvel' => 3500,
1769
'legacy_first_avenger' => 3501,
1770
'fenix6s_sport_asia' => 3512,
1771
'fenix6s_asia' => 3513,
1772
'fenix6_sport_asia' => 3514,
1773
'fenix6_asia' => 3515,
1774
'fenix6x_asia' => 3516,
1775
'legacy_captain_marvel_asia' => 3535,
1776
'legacy_first_avenger_asia' => 3536,
1777
'legacy_rey_asia' => 3537,
1778
'legacy_darth_vader_asia' => 3538,
1779
'descent_mk2s' => 3542,
1780
'edge_130_plus' => 3558,
1781
'edge_1030_plus' => 3570,
1782
'rally_200' => 3578, # Rally 100/200 Power Meter Series
1783
'fr745' => 3589,
1784
'venusq' => 3600,
1785
'lily' => 3615,
1786
'marq_adventurer' => 3624,
1787
'enduro' => 3638,
1788
'swim2_apac' => 3639,
1789
'marq_adventurer_asia' => 3648,
1790
'fr945_lte' => 3652,
1791
'descent_mk2_asia' => 3702, # Mk2 and Mk2i
1792
'venu2' => 3703,
1793
'venu2s' => 3704,
1794
'venu_daimler_asia' => 3737,
1795
'marq_golfer' => 3739,
1796
'venu_daimler' => 3740,
1797
'fr745_asia' => 3794,
1798
'lily_asia' => 3809,
1799
'edge_1030_plus_asia' => 3812,
1800
'edge_130_plus_asia' => 3813,
1801
'approach_s12' => 3823,
1802
'enduro_asia' => 3872,
1803
'venusq_asia' => 3837,
1804
'edge_1040' => 3843,
1805
'marq_golfer_asia' => 3850,
1806
'venu2_plus' => 3851,
1807
'fr55' => 3869,
1808
'instinct_2' => 3888,
1809
'fenix7s' => 3905,
1810
'fenix7' => 3906,
1811
'fenix7x' => 3907,
1812
'fenix7s_apac' => 3908,
1813
'fenix7_apac' => 3909,
1814
'fenix7x_apac' => 3910,
1815
'approach_g12' => 3927,
1816
'descent_mk2s_asia' => 3930,
1817
'approach_s42' => 3934,
1818
'epix_gen2' => 3943,
1819
'epix_gen2_apac' => 3944,
1820
'venu2s_asia' => 3949,
1821
'venu2_asia' => 3950,
1822
'fr945_lte_asia' => 3978,
1823
'vivo_move_sport' => 3982,
1824
'vivomove_trend' => 3983,
1825
'approach_S12_asia' => 3986,
1826
'fr255_music' => 3990,
1827
'fr255_small_music' => 3991,
1828
'fr255' => 3992,
1829
'fr255_small' => 3993,
1830
'approach_g12_asia' => 4001,
1831
'approach_s42_asia' => 4002,
1832
'descent_g1' => 4005,
1833
'venu2_plus_asia' => 4017,
1834
'fr955' => 4024,
1835
'fr55_asia' => 4033,
1836
'vivosmart_5' => 4063,
1837
'instinct_2_asia' => 4071,
1838
'marq_gen2' => 4105, # Adventurer, Athlete, Captain, Golfer
1839
'venusq2' => 4115,
1840
'venusq2music' => 4116,
1841
'marq_gen2_aviator' => 4124,
1842
'd2_air_x10' => 4125,
1843
'hrm_pro_plus' => 4130,
1844
'descent_g1_asia' => 4132,
1845
'tactix7' => 4135,
1846
'instinct_crossover' => 4155,
1847
'edge_explore2' => 4169,
1848
'tacx_neo_smart' => 4265, # Neo Smart, Tacx
1849
'tacx_neo2_smart' => 4266, # Neo 2 Smart, Tacx
1850
'tacx_neo2_t_smart' => 4267, # Neo 2T Smart, Tacx
1851
'tacx_neo_smart_bike' => 4268, # Neo Smart Bike, Tacx
1852
'tacx_satori_smart' => 4269, # Satori Smart, Tacx
1853
'tacx_flow_smart' => 4270, # Flow Smart, Tacx
1854
'tacx_vortex_smart' => 4271, # Vortex Smart, Tacx
1855
'tacx_bushido_smart' => 4272, # Bushido Smart, Tacx
1856
'tacx_genius_smart' => 4273, # Genius Smart, Tacx
1857
'tacx_flux_flux_s_smart' => 4274, # Flux/Flux S Smart, Tacx
1858
'tacx_flux2_smart' => 4275, # Flux 2 Smart, Tacx
1859
'tacx_magnum' => 4276, # Magnum, Tacx
1860
'edge_1040_asia' => 4305,
1861
'enduro2' => 4341,
1862
'sdm4' => 10007, # SDM4 footpod
1863
'edge_remote' => 10014,
1864
'tacx_training_app_win' => 20533,
1865
'tacx_training_app_mac' => 20534,
1866
'tacx_training_app_mac_catalyst' => 20565,
1867
'training_center' => 20119,
1868
'tacx_training_app_android' => 30045,
1869
'tacx_training_app_ios' => 30046,
1870
'tacx_training_app_legacy' => 30047,
1871
'connectiq_simulator' => 65531,
1872
'android_antplus_plugin' => 65532,
1873
'connect' => 65534, # Garmin Connect website
1874
},
1875
1876
'device_type' => +{
1877
'_moved_to' => 'antplus_device_type',
1878
},
1879
1880
'antplus_device_type' => +{
1881
'_base_type' => FIT_UINT8,
1882
'antfs' => 1,
1883
'bike_power' => 11,
1884
'environment_sensor_legacy' => 12,
1885
'multi_sport_speed_distance' => 15,
1886
'control' => 16,
1887
'fitness_equipment' => 17,
1888
'blood_pressure' => 18,
1889
'geocache_node' => 19,
1890
'light_electric_vehicle' => 20,
1891
'env_sensor' => 25,
1892
'racquet' => 26,
1893
'control_hub' => 27,
1894
'muscle_oxygen' => 31,
1895
'shifting' => 34,
1896
'bike_light_main' => 35,
1897
'bike_light_shared' => 36,
1898
'exd' => 38,
1899
'bike_radar' => 40,
1900
'bike_aero' => 46,
1901
'weight_scale' => 119,
1902
'heart_rate' => 120,
1903
'bike_speed_cadence' => 121,
1904
'bike_cadence' => 122,
1905
'bike_speed' => 123,
1906
'stride_speed_distance' => 124,
1907
},
1908
1909
'ant_network' => +{
1910
'_base_type' => FIT_ENUM,
1911
'public' => 0,
1912
'antplus' => 1,
1913
'antfs' => 2,
1914
'private' => 3,
1915
},
1916
1917
'workout_capabilities' => +{
1918
'_base_type' => FIT_UINT32Z,
1919
'_mask' => 1,
1920
'interval' => 0x00000001,
1921
'custom' => 0x00000002,
1922
'fitness_equipment' => 0x00000004,
1923
'firstbeat' => 0x00000008,
1924
'new_leaf' => 0x00000010,
1925
'tcx' => 0x00000020,
1926
'speed' => 0x00000080,
1927
'heart_rate' => 0x00000100,
1928
'distance' => 0x00000200,
1929
'cadence' => 0x00000400,
1930
'power' => 0x00000800,
1931
'grade' => 0x00001000,
1932
'resistance' => 0x00002000,
1933
'protected' => 0x00004000,
1934
},
1935
1936
'battery_status' => +{
1937
'_base_type' => FIT_UINT8,
1938
'new' => 1,
1939
'good' => 2,
1940
'ok' => 3,
1941
'low' => 4,
1942
'critical' => 5,
1943
'charging' => 6,
1944
'unknown' => 7,
1945
},
1946
1947
'hr_type' => +{
1948
'_base_type' => FIT_ENUM,
1949
'normal' => 0,
1950
'irregular' => 1,
1951
},
1952
1953
'course_capabilities' => +{
1954
'_base_type' => FIT_UINT32Z,
1955
'_mask' => 1,
1956
'processed' => 0x00000001,
1957
'valid' => 0x00000002,
1958
'time' => 0x00000004,
1959
'distance' => 0x00000008,
1960
'position' => 0x00000010,
1961
'heart_rate' => 0x00000020,
1962
'power' => 0x00000040,
1963
'cadence' => 0x00000080,
1964
'training' => 0x00000100,
1965
'navigation' => 0x00000200,
1966
'bikeway' => 0x00000400,
1967
'aviation'=> 0x00001000, # Denote course files to be used as flight plans
1968
},
1969
1970
'weight' => +{
1971
'_base_type' => FIT_UINT16,
1972
'calculating' => 0xFFFE,
1973
},
1974
1975
'workout_hr' => +{
1976
'_base_type' => FIT_UINT32,
1977
'bpm_offset' => 100,
1978
},
1979
1980
'workout_power' => +{
1981
'_base_type' => FIT_UINT32,
1982
'watts_offset' => 1000,
1983
},
1984
1985
'bp_status' => +{
1986
'_base_type' => FIT_ENUM,
1987
'no_error' => 0,
1988
'error_incomplete_data' => 1,
1989
'error_no_measurement' => 2,
1990
'error_data_out_of_range' => 3,
1991
'error_irregular_heart_rate' => 4,
1992
},
1993
1994
'user_local_id' => +{
1995
'_base_type' => FIT_UINT16,
1996
'local_min' => 0x0001,
1997
'local_max' => 0x000F,
1998
'stationary_min' => 0x0010,
1999
'stationary_max' => 0x00FF,
2000
'portable_min' => 0x0100,
2001
'portable_max' => 0xFFFE,
2002
},
2003
2004
'swim_stroke' => +{
2005
'_base_type' => FIT_ENUM,
2006
'freestyle' => 0,
2007
'backstroke' => 1,
2008
'breaststroke' => 2,
2009
'butterfly' => 3,
2010
'drill' => 4,
2011
'mixed' => 5,
2012
'im' => 6,
2013
},
2014
2015
'activity_type' => +{
2016
'_base_type' => FIT_ENUM,
2017
'generic' => 0,
2018
'running' => 1,
2019
'cycling' => 2,
2020
'transition' => 3,
2021
'fitness_equipment' => 4,
2022
'swimming' => 5,
2023
'walking' => 6,
2024
'sedentary' => 8,
2025
'all' => 254,
2026
},
2027
2028
'activity_subtype' => +{
2029
'_base_type' => FIT_ENUM,
2030
'generic' => 0,
2031
'treadmill' => 1, # run
2032
'street' => 2, # run
2033
'trail' => 3, # run
2034
'track' => 4, # run
2035
'spin' => 5, # cycling
2036
'indoor_cycling' => 6, # cycling
2037
'road' => 7, # cycling
2038
'mountain' => 8, # cycling
2039
'downhill' => 9, # cycling
2040
'recumbent' => 10, # cycling
2041
'cyclocross' => 11, # cycling
2042
'hand_cycling' => 12, # cycling
2043
'track_cycling' => 13, # cycling
2044
'indoor_rowing' => 14, # fitness equipment
2045
'elliptical' => 15, # fitness equipment
2046
'stair_climbing' => 16, # fitness equipment
2047
'lap_swimming' => 17, # swimming
2048
'open_water' => 18, # swimming
2049
'all' => 254,
2050
},
2051
2052
'activity_level' => +{
2053
'_base_type' => FIT_ENUM,
2054
'low' => 0,
2055
'medium' => 1,
2056
'high' => 2,
2057
},
2058
2059
'side' => +{
2060
'_base_type' => FIT_ENUM,
2061
'right' => 0,
2062
'left' => 1,
2063
},
2064
2065
'left_right_balance' => +{
2066
'_base_type' => FIT_UINT8,
2067
'mask' => 0x7F,
2068
'right' => 0x80,
2069
},
2070
2071
'left_right_balance_100' => +{
2072
'_base_type' => FIT_UINT16,
2073
'mask' => 0x3FFF,
2074
'right' => 0x8000,
2075
},
2076
2077
'length_type' => +{
2078
'_base_type' => FIT_ENUM,
2079
'idle' => 0,
2080
'active' => 1,
2081
},
2082
2083
'day_of_week' => +{
2084
'_base_type' => FIT_ENUM,
2085
'sunday' => 0,
2086
'monday' => 1,
2087
'tuesday' => 2,
2088
'wednesday' => 3,
2089
'thursday' => 4,
2090
'friday' => 5,
2091
'saturday' => 6,
2092
},
2093
2094
'connectivity_capabilities' => +{
2095
'_base_type' => FIT_UINT32Z,
2096
'bluetooth' => 0x00000001,
2097
'bluetooth_le' => 0x00000002,
2098
'ant' => 0x00000004,
2099
'activity_upload' => 0x00000008,
2100
'course_download' => 0x00000010,
2101
'workout_download' => 0x00000020,
2102
'live_track' => 0x00000040,
2103
'weather_conditions' => 0x00000080,
2104
'weather_alerts' => 0x00000100,
2105
'gps_ephemeris_download' => 0x00000200,
2106
'explicit_archive' => 0x00000400,
2107
'setup_incomplete' => 0x00000800,
2108
'continue_sync_after_software_update' => 0x00001000,
2109
'connect_iq_app_download' => 0x00002000,
2110
'golf_course_download' => 0x00004000,
2111
'device_initiates_sync' => 0x00008000,
2112
'connect_iq_watch_app_download' => 0x00010000,
2113
'connect_iq_widget_download' => 0x00020000,
2114
'connect_iq_watch_face_download' => 0x00040000,
2115
'connect_iq_data_field_download' => 0x00080000,
2116
'connect_iq_app_managment' => 0x00100000,
2117
'swing_sensor' => 0x00200000,
2118
'swing_sensor_remote' => 0x00400000,
2119
'incident_detection' => 0x00800000,
2120
'audio_prompts' => 0x01000000,
2121
'wifi_verification' => 0x02000000,
2122
'true_up' => 0x04000000,
2123
'find_my_watch' => 0x08000000,
2124
'remote_manual_sync' => 0x10000000,
2125
'live_track_auto_start' => 0x20000000,
2126
'live_track_messaging' => 0x40000000,
2127
'instant_input' => 0x80000000, # Device supports instant input feature
2128
},
2129
2130
'weather_report' => +{
2131
'_base_type' => FIT_ENUM,
2132
'current' => 0,
2133
# 'forecast' => 1, # deprecated, use hourly_forecast instead
2134
'hourly_forecast' => 1,
2135
'daily_forecast' => 2,
2136
},
2137
2138
'weather_status' => +{
2139
'_base_type' => FIT_ENUM,
2140
'clear' => 0,
2141
'partly_cloudy' => 1,
2142
'mostly_cloudy' => 2,
2143
'rain' => 3,
2144
'snow' => 4,
2145
'windy' => 5,
2146
'thunderstorms' => 6,
2147
'wintry_mix' => 7,
2148
'fog' => 8,
2149
'hazy' => 11,
2150
'hail' => 12,
2151
'scattered_showers' => 13,
2152
'scattered_thunderstorms' => 14,
2153
'unknown_precipitation' => 15,
2154
'light_rain' => 16,
2155
'heavy_rain' => 17,
2156
'light_snow' => 18,
2157
'heavy_snow' => 19,
2158
'light_rain_snow' => 20,
2159
'heavy_rain_snow' => 21,
2160
'cloudy' => 22,
2161
},
2162
2163
'weather_severity' => +{
2164
'_base_type' => FIT_ENUM,
2165
'unknown' => 0,
2166
'warning' => 1,
2167
'watch' => 2,
2168
'advisory' => 3,
2169
'statement' => 4,
2170
},
2171
2172
'weather_severe_type' => +{
2173
'_base_type' => FIT_ENUM,
2174
'unspecified' => 0,
2175
'tornado' => 1,
2176
'tsunami' => 2,
2177
'hurricane' => 3,
2178
'extreme_wind' => 4,
2179
'typhoon' => 5,
2180
'inland_hurricane' => 6,
2181
'hurricane_force_wind' => 7,
2182
'waterspout' => 8,
2183
'severe_thunderstorm' => 9,
2184
'wreckhouse_winds' => 10,
2185
'les_suetes_wind' => 11,
2186
'avalanche' => 12,
2187
'flash_flood' => 13,
2188
'tropical_storm' => 14,
2189
'inland_tropical_storm' => 15,
2190
'blizzard' => 16,
2191
'ice_storm' => 17,
2192
'freezing_rain' => 18,
2193
'debris_flow' => 19,
2194
'flash_freeze' => 20,
2195
'dust_storm' => 21,
2196
'high_wind' => 22,
2197
'winter_storm' => 23,
2198
'heavy_freezing_spray' => 24,
2199
'extreme_cold' => 25,
2200
'wind_chill' => 26,
2201
'cold_wave' => 27,
2202
'heavy_snow_alert' => 28,
2203
'lake_effect_blowing_snow' => 29,
2204
'snow_squall' => 30,
2205
'lake_effect_snow' => 31,
2206
'winter_weather' => 32,
2207
'sleet' => 33,
2208
'snowfall' => 34,
2209
'snow_and_blowing_snow' => 35,
2210
'blowing_snow' => 36,
2211
'snow_alert' => 37,
2212
'arctic_outflow' => 38,
2213
'freezing_drizzle' => 39,
2214
'storm' => 40,
2215
'storm_surge' => 41,
2216
'rainfall' => 42,
2217
'areal_flood' => 43,
2218
'coastal_flood' => 44,
2219
'lakeshore_flood' => 45,
2220
'excessive_heat' => 46,
2221
'heat' => 47,
2222
'weather' => 48,
2223
'high_heat_and_humidity' => 49,
2224
'humidex_and_health' => 50,
2225
'humidex' => 51,
2226
'gale' => 52,
2227
'freezing_spray' => 53,
2228
'special_marine' => 54,
2229
'squall' => 55,
2230
'strong_wind' => 56,
2231
'lake_wind' => 57,
2232
'marine_weather' => 58,
2233
'wind' => 59,
2234
'small_craft_hazardous_seas' => 60,
2235
'hazardous_seas' => 61,
2236
'small_craft' => 62,
2237
'small_craft_winds' => 63,
2238
'small_craft_rough_bar' => 64,
2239
'high_water_level' => 65,
2240
'ashfall' => 66,
2241
'freezing_fog' => 67,
2242
'dense_fog' => 68,
2243
'dense_smoke' => 69,
2244
'blowing_dust' => 70,
2245
'hard_freeze' => 71,
2246
'freeze' => 72,
2247
'frost' => 73,
2248
'fire_weather' => 74,
2249
'flood' => 75,
2250
'rip_tide' => 76,
2251
'high_surf' => 77,
2252
'smog' => 78,
2253
'air_quality' => 79,
2254
'brisk_wind' => 80,
2255
'air_stagnation' => 81,
2256
'low_water' => 82,
2257
'hydrological' => 83,
2258
'special_weather' => 84,
2259
},
2260
2261
'time_into_day' => +{ # since 00:00:00 UTC
2262
'_base_type' => FIT_UINT32,
2263
},
2264
2265
'localtime_into_day' => +{ # same as above, but in local time zone
2266
'_base_type' => FIT_UINT32,
2267
},
2268
2269
'stroke_type' => +{
2270
'_base_type' => FIT_ENUM,
2271
'no_event' => 0,
2272
'other' => 1,
2273
'serve' => 2,
2274
'forehand' => 3,
2275
'backhand' => 4,
2276
'smash' => 5,
2277
},
2278
2279
'body_location' => +{
2280
'_base_type' => FIT_ENUM,
2281
'left_leg' => 0,
2282
'left_calf' => 1,
2283
'left_shin' => 2,
2284
'left_hamstring' => 3,
2285
'left_quad' => 4,
2286
'left_glute' => 5,
2287
'right_leg' => 6,
2288
'right_calf' => 7,
2289
'right_shin' => 8,
2290
'right_hamstring' => 9,
2291
'right_quad' => 10,
2292
'right_glute' => 11,
2293
'torso_back' => 12,
2294
'left_lower_back' => 13,
2295
'left_upper_back' => 14,
2296
'right_lower_back' => 15,
2297
'right_upper_back' => 16,
2298
'torso_front' => 17,
2299
'left_abdomen' => 18,
2300
'left_chest' => 19,
2301
'right_abdomen' => 20,
2302
'right_chest' => 21,
2303
'left_arm' => 22,
2304
'left_shoulder' => 23,
2305
'left_bicep' => 24,
2306
'left_tricep' => 25,
2307
'left_brachioradialis' => 26,
2308
'left_forearm_extensors' => 27,
2309
'right_arm' => 28,
2310
'right_shoulder' => 29,
2311
'right_bicep' => 30,
2312
'right_tricep' => 31,
2313
'right_brachioradialis' => 32,
2314
'right_forearm_extensors' => 33,
2315
'neck' => 34,
2316
'throat' => 35,
2317
'waist_mid_back' => 36,
2318
'waist_front' => 37,
2319
'waist_left' => 38,
2320
'waist_right' => 39,
2321
},
2322
2323
'segment_lap_status' => +{
2324
'_base_type' => FIT_ENUM,
2325
'end' => 0,
2326
'fail' => 1,
2327
},
2328
2329
'segment_leaderboard_type' => +{
2330
'_base_type' => FIT_ENUM,
2331
'overall' => 0,
2332
'personal_best' => 1,
2333
'connections' => 2,
2334
'group' => 3,
2335
'challenger' => 4,
2336
'kom' => 5,
2337
'qom' => 6,
2338
'pr' => 7,
2339
'goal' => 8,
2340
'rival' => 9,
2341
'club_leader' => 10,
2342
},
2343
2344
'segment_delete_status' => +{
2345
'_base_type' => FIT_ENUM,
2346
'do_not_delete' => 0,
2347
'delete_one' => 1,
2348
'delete_all' => 2,
2349
},
2350
2351
'segment_selection_type' => +{
2352
'_base_type' => FIT_ENUM,
2353
'starred' => 0,
2354
'suggested' => 1,
2355
},
2356
2357
'source_type' => +{
2358
'_base_type' => FIT_ENUM,
2359
'ant' => 0,
2360
'antplus' => 1,
2361
'bluetooth' => 2,
2362
'bluetooth_low_energy' => 3,
2363
'wifi' => 4,
2364
'local' => 5,
2365
},
2366
2367
'local_device_type' => +{
2368
'_base_type' => FIT_UINT8,
2369
'gps' => 0, # Onboard gps receiver
2370
'glonass' => 1, # Onboard glonass receiver
2371
'gps_glonass' => 2, # Onboard gps glonass receiver
2372
'accelerometer' => 3, # Onboard sensor
2373
'barometer' => 4, # Onboard sensor
2374
'temperature' => 5, # Onboard sensor
2375
'whr' => 10, # Onboard wrist HR sensor
2376
'sensor_hub' => 12, # Onboard software package
2377
},
2378
2379
'ble_device_type' => +{
2380
'_base_type' => FIT_ENUM,
2381
'connected_gps' => 0, # GPS that is provided over a proprietary bluetooth service
2382
'heart_rate' => 1,
2383
'bike_power' => 2,
2384
'bike_speed_cadence' => 3,
2385
'bike_speed' => 4,
2386
'bike_cadence' => 5,
2387
'footpod' => 6,
2388
'bike_trainer' => 7, # Indoor-Bike FTMS protocol
2389
},
2390
2391
'ant_channel_id' => +{
2392
'_base_type' => FIT_UINT32Z,
2393
'ant_extended_device_number_upper_nibble' => 0xF0000000,
2394
'ant_transmission_type_lower_nibble' => 0x0F000000,
2395
'ant_device_type' => 0x00FF0000,
2396
'ant_device_number' => 0x0000FFFF,
2397
},
2398
2399
'display_orientation' => +{
2400
'_base_type' => FIT_ENUM,
2401
'auto' => 0,
2402
'portrait' => 1,
2403
'landscape' => 2,
2404
'portrait_flipped' => 3,
2405
'landscape_flipped' => 4,
2406
},
2407
2408
'workout_equipment' => +{
2409
'_base_type' => FIT_ENUM,
2410
'none' => 0,
2411
'swim_fins' => 1,
2412
'swim_kickboard' => 2,
2413
'swim_paddles' => 3,
2414
'swim_pull_buoy' => 4,
2415
'swim_snorkel' => 5,
2416
},
2417
'watchface_mode' => +{
2418
'_base_type' => FIT_ENUM,
2419
'digital' => 0,
2420
'analog' => 1,
2421
'connect_iq' => 2,
2422
'disabled' => 3,
2423
},
2424
2425
'digital_watchface_layout' => +{
2426
'_base_type' => FIT_ENUM,
2427
'traditional' => 0,
2428
'modern' => 1,
2429
'bold' => 2,
2430
},
2431
2432
'analog_watchface_layout' => +{
2433
'_base_type' => FIT_ENUM,
2434
'minimal' => 0,
2435
'traditional' => 1,
2436
'modern' => 2,
2437
},
2438
2439
'rider_position_type' => +{
2440
'_base_type' => FIT_ENUM,
2441
'seated' => 0,
2442
'standing' => 1,
2443
'transition_to_seated' => 2,
2444
'transition_to_standing' => 3,
2445
},
2446
2447
'power_phase_type' => +{
2448
'_base_type' => FIT_ENUM,
2449
'power_phase_start_angle' => 0,
2450
'power_phase_end_angle' => 1,
2451
'power_phase_arc_length' => 2,
2452
'power_phase_center' => 3,
2453
},
2454
2455
'camera_event_type' => +{
2456
'_base_type' => FIT_ENUM,
2457
'video_start' => 0,
2458
'video_split' => 1,
2459
'video_end' => 2,
2460
'photo_taken' => 3,
2461
'video_second_stream_start' => 4,
2462
'video_second_stream_split' => 5,
2463
'video_second_stream_end' => 6,
2464
'video_split_start' => 7,
2465
'video_second_stream_split_start' => 8,
2466
'video_pause' => 11,
2467
'video_second_stream_pause' => 12,
2468
'video_resume' => 13,
2469
'video_second_stream_resume' => 14,
2470
},
2471
2472
'sensor_type' => +{
2473
'_base_type' => FIT_ENUM,
2474
'accelerometer' => 0,
2475
'gyroscope' => 1,
2476
'compass' => 2, # Magnetometer
2477
'barometer' => 3,
2478
},
2479
2480
'bike_light_network_config_type' => +{
2481
'_base_type' => FIT_ENUM,
2482
'auto' => 0,
2483
'individual' => 4,
2484
'high_visibility' => 5,
2485
'trail' => 6,
2486
},
2487
2488
'comm_timeout_type' => +{
2489
'_base_type' => FIT_UINT16,
2490
'wildcard_pairing_timeout' => 0,
2491
'pairing_timeout' => 1,
2492
'connection_lost' => 2,
2493
'connection_timeout' => 3,
2494
},
2495
2496
'camera_orientation_type' => +{
2497
'_base_type' => FIT_ENUM,
2498
'camera_orientation_0' => 0,
2499
'camera_orientation_90' => 1,
2500
'camera_orientation_180' => 2,
2501
'camera_orientation_270' => 3,
2502
},
2503
2504
'attitude_stage' => +{
2505
'_base_type' => FIT_ENUM,
2506
'failed' => 0,
2507
'aligning' => 1,
2508
'degraded' => 2,
2509
'valid' => 3,
2510
},
2511
2512
'attitude_validity' => +{
2513
'_base_type' => FIT_UINT16,
2514
'track_angle_heading_valid' => 0x0001,
2515
'pitch_valid' => 0x0002,
2516
'roll_valid' => 0x0004,
2517
'lateral_body_accel_valid' => 0x0008,
2518
'normal_body_accel_valid' => 0x0010,
2519
'turn_rate_valid' => 0x0020,
2520
'hw_fail' => 0x0040,
2521
'mag_invalid' => 0x0080,
2522
'no_gps' => 0x0100,
2523
'gps_invalid' => 0x0200,
2524
'solution_coasting' => 0x0400,
2525
'true_track_angle' => 0x0800,
2526
'magnetic_heading' => 0x1000,
2527
},
2528
2529
'auto_sync_frequency' => +{
2530
'_base_type' => FIT_ENUM,
2531
'never' => 0,
2532
'occasionally' => 1,
2533
'frequent' => 2,
2534
'once_a_day' => 3,
2535
'remote' => 4,
2536
},
2537
2538
'exd_layout' => +{
2539
'_base_type' => FIT_ENUM,
2540
'full_screen' => 0,
2541
'half_vertical' => 1,
2542
'half_horizontal' => 2,
2543
'half_vertical_right_split' => 3,
2544
'half_horizontal_bottom_split' => 4,
2545
'full_quarter_split' => 5,
2546
'half_vertical_left_split' => 6,
2547
'half_horizontal_top_split' => 7,
2548
'dynamic' => 8, # The EXD may display the configured concepts in any layout it sees fit.
2549
},
2550
2551
'exd_display_type' => +{
2552
'_base_type' => FIT_ENUM,
2553
'numerical' => 0,
2554
'simple' => 1,
2555
'graph' => 2,
2556
'bar' => 3,
2557
'circle_graph' => 4,
2558
'virtual_partner' => 5,
2559
'balance' => 6,
2560
'string_list' => 7,
2561
'string' => 8,
2562
'simple_dynamic_icon' => 9,
2563
'gauge' => 10,
2564
},
2565
2566
'exd_data_units' => +{
2567
'_base_type' => FIT_ENUM,
2568
'no_units' => 0,
2569
'laps' => 1,
2570
'miles_per_hour' => 2,
2571
'kilometers_per_hour' => 3,
2572
'feet_per_hour' => 4,
2573
'meters_per_hour' => 5,
2574
'degrees_celsius' => 6,
2575
'degrees_farenheit' => 7,
2576
'zone' => 8,
2577
'gear' => 9,
2578
'rpm' => 10,
2579
'bpm' => 11,
2580
'degrees' => 12,
2581
'millimeters' => 13,
2582
'meters' => 14,
2583
'kilometers' => 15,
2584
'feet' => 16,
2585
'yards' => 17,
2586
'kilofeet' => 18,
2587
'miles' => 19,
2588
'time' => 20,
2589
'enum_turn_type' => 21,
2590
'percent' => 22,
2591
'watts' => 23,
2592
'watts_per_kilogram' => 24,
2593
'enum_battery_status' => 25,
2594
'enum_bike_light_beam_angle_mode' => 26,
2595
'enum_bike_light_battery_status' => 27,
2596
'enum_bike_light_network_config_type' => 28,
2597
'lights' => 29,
2598
'seconds' => 30,
2599
'minutes' => 31,
2600
'hours' => 32,
2601
'calories' => 33,
2602
'kilojoules' => 34,
2603
'milliseconds' => 35,
2604
'second_per_mile' => 36,
2605
'second_per_kilometer' => 37,
2606
'centimeter' => 38,
2607
'enum_course_point' => 39,
2608
'bradians' => 40,
2609
'enum_sport' => 41,
2610
'inches_hg' => 42,
2611
'mm_hg' => 43,
2612
'mbars' => 44,
2613
'hecto_pascals' => 45,
2614
'feet_per_min' => 46,
2615
'meters_per_min' => 47,
2616
'meters_per_sec' => 48,
2617
'eight_cardinal' => 49,
2618
},
2619
2620
'exd_qualifiers' => +{
2621
'_base_type' => FIT_ENUM,
2622
'no_qualifier' => 0,
2623
'instantaneous' => 1,
2624
'average' => 2,
2625
'lap' => 3,
2626
'maximum' => 4,
2627
'maximum_average' => 5,
2628
'maximum_lap' => 6,
2629
'last_lap' => 7,
2630
'average_lap' => 8,
2631
'to_destination' => 9,
2632
'to_go' => 10,
2633
'to_next' => 11,
2634
'next_course_point' => 12,
2635
'total' => 13,
2636
'three_second_average' => 14,
2637
'ten_second_average' => 15,
2638
'thirty_second_average' => 16,
2639
'percent_maximum' => 17,
2640
'percent_maximum_average' => 18,
2641
'lap_percent_maximum' => 19,
2642
'elapsed' => 20,
2643
'sunrise' => 21,
2644
'sunset' => 22,
2645
'compared_to_virtual_partner' => 23,
2646
'maximum_24h' => 24,
2647
'minimum_24h' => 25,
2648
'minimum' => 26,
2649
'first' => 27,
2650
'second' => 28,
2651
'third' => 29,
2652
'shifter' => 30,
2653
'last_sport' => 31,
2654
'moving' => 32,
2655
'stopped' => 33,
2656
'estimated_total' => 34,
2657
'zone_9' => 242,
2658
'zone_8' => 243,
2659
'zone_7' => 244,
2660
'zone_6' => 245,
2661
'zone_5' => 246,
2662
'zone_4' => 247,
2663
'zone_3' => 248,
2664
'zone_2' => 249,
2665
'zone_1' => 250,
2666
},
2667
2668
'exd_descriptors' => +{
2669
'_base_type' => FIT_ENUM,
2670
'bike_light_battery_status' => 0,
2671
'beam_angle_status' => 1,
2672
'batery_level' => 2,
2673
'light_network_mode' => 3,
2674
'number_lights_connected' => 4,
2675
'cadence' => 5,
2676
'distance' => 6,
2677
'estimated_time_of_arrival' => 7,
2678
'heading' => 8,
2679
'time' => 9,
2680
'battery_level' => 10,
2681
'trainer_resistance' => 11,
2682
'trainer_target_power' => 12,
2683
'time_seated' => 13,
2684
'time_standing' => 14,
2685
'elevation' => 15,
2686
'grade' => 16,
2687
'ascent' => 17,
2688
'descent' => 18,
2689
'vertical_speed' => 19,
2690
'di2_battery_level' => 20,
2691
'front_gear' => 21,
2692
'rear_gear' => 22,
2693
'gear_ratio' => 23,
2694
'heart_rate' => 24,
2695
'heart_rate_zone' => 25,
2696
'time_in_heart_rate_zone' => 26,
2697
'heart_rate_reserve' => 27,
2698
'calories' => 28,
2699
'gps_accuracy' => 29,
2700
'gps_signal_strength' => 30,
2701
'temperature' => 31,
2702
'time_of_day' => 32,
2703
'balance' => 33,
2704
'pedal_smoothness' => 34,
2705
'power' => 35,
2706
'functional_threshold_power' => 36,
2707
'intensity_factor' => 37,
2708
'work' => 38,
2709
'power_ratio' => 39,
2710
'normalized_power' => 40,
2711
'training_stress_score' => 41,
2712
'time_on_zone' => 42,
2713
'speed' => 43,
2714
'laps' => 44,
2715
'reps' => 45,
2716
'workout_step' => 46,
2717
'course_distance' => 47,
2718
'navigation_distance' => 48,
2719
'course_estimated_time_of_arrival' => 49,
2720
'navigation_estimated_time_of_arrival' => 50,
2721
'course_time' => 51,
2722
'navigation_time' => 52,
2723
'course_heading' => 53,
2724
'navigation_heading' => 54,
2725
'power_zone' => 55,
2726
'torque_effectiveness' => 56,
2727
'timer_time' => 57,
2728
'power_weight_ratio' => 58,
2729
'left_platform_center_offset' => 59,
2730
'right_platform_center_offset' => 60,
2731
'left_power_phase_start_angle' => 61,
2732
'right_power_phase_start_angle' => 62,
2733
'left_power_phase_finish_angle' => 63,
2734
'right_power_phase_finish_angle' => 64,
2735
'gears' => 65,
2736
'pace' => 66,
2737
'training_effect' => 67,
2738
'vertical_oscillation' => 68,
2739
'vertical_ratio' => 69,
2740
'ground_contact_time' => 70,
2741
'left_ground_contact_time_balance' => 71,
2742
'right_ground_contact_time_balance' => 72,
2743
'stride_length' => 73,
2744
'running_cadence' => 74,
2745
'performance_condition' => 75,
2746
'course_type' => 76,
2747
'time_in_power_zone' => 77,
2748
'navigation_turn' => 78,
2749
'course_location' => 79,
2750
'navigation_location' => 80,
2751
'compass' => 81,
2752
'gear_combo' => 82,
2753
'muscle_oxygen' => 83,
2754
'icon' => 84,
2755
'compass_heading' => 85,
2756
'gps_heading' => 86,
2757
'gps_elevation' => 87,
2758
'anaerobic_training_effect' => 88,
2759
'course' => 89,
2760
'off_course' => 90,
2761
'glide_ratio' => 91,
2762
'vertical_distance' => 92,
2763
'vmg' => 93,
2764
'ambient_pressure' => 94,
2765
'pressure' => 95,
2766
'vam' => 96,
2767
},
2768
2769
'auto_activity_detect' => +{
2770
'_base_type' => FIT_UINT32,
2771
'none' => 0x00000000,
2772
'running' => 0x00000001,
2773
'cycling' => 0x00000002,
2774
'swimming' => 0x00000004,
2775
'walking' => 0x00000008,
2776
'elliptical' => 0x00000020,
2777
'sedentary' => 0x00000400,
2778
},
2779
2780
'supported_exd_screen_layouts' => +{
2781
'_base_type' => FIT_UINT32Z,
2782
'full_screen' => 0x00000001,
2783
'half_vertical' => 0x00000002,
2784
'half_horizontal' => 0x00000004,
2785
'half_vertical_right_split' => 0x00000008,
2786
'half_horizontal_bottom_split' => 0x00000010,
2787
'full_quarter_split' => 0x00000020,
2788
'half_vertical_left_split' => 0x00000040,
2789
'half_horizontal_top_split' => 0x00000080,
2790
},
2791
2792
'fit_base_type' => +{
2793
'_base_type' => FIT_UINT8,
2794
'enum' => 0,
2795
'sint8' => 1,
2796
'uint8' => 2,
2797
'sint16' => 131,
2798
'uint16' => 132,
2799
'sint32' => 133,
2800
'uint32' => 134,
2801
'string' => 7,
2802
'float32' => 136,
2803
'float64' => 137,
2804
'uint8z' => 10,
2805
'uint16z' => 139,
2806
'uint32z' => 140,
2807
'byte' => 13,
2808
'sint64' => 142,
2809
'uint64' => 143,
2810
'uint64z' => 144,
2811
},
2812
2813
'turn_type' => +{
2814
'_base_type' => FIT_ENUM,
2815
'arriving_idx' => 0,
2816
'arriving_left_idx' => 1,
2817
'arriving_right_idx' => 2,
2818
'arriving_via_idx' => 3,
2819
'arriving_via_left_idx' => 4,
2820
'arriving_via_right_idx' => 5,
2821
'bear_keep_left_idx' => 6,
2822
'bear_keep_right_idx' => 7,
2823
'continue_idx' => 8,
2824
'exit_left_idx' => 9,
2825
'exit_right_idx' => 10,
2826
'ferry_idx' => 11,
2827
'roundabout_45_idx' => 12,
2828
'roundabout_90_idx' => 13,
2829
'roundabout_135_idx' => 14,
2830
'roundabout_180_idx' => 15,
2831
'roundabout_225_idx' => 16,
2832
'roundabout_270_idx' => 17,
2833
'roundabout_315_idx' => 18,
2834
'roundabout_360_idx' => 19,
2835
'roundabout_neg_45_idx' => 20,
2836
'roundabout_neg_90_idx' => 21,
2837
'roundabout_neg_135_idx' => 22,
2838
'roundabout_neg_180_idx' => 23,
2839
'roundabout_neg_225_idx' => 24,
2840
'roundabout_neg_270_idx' => 25,
2841
'roundabout_neg_315_idx' => 26,
2842
'roundabout_neg_360_idx' => 27,
2843
'roundabout_generic_idx' => 28,
2844
'roundabout_neg_generic_idx' => 29,
2845
'sharp_turn_left_idx' => 30,
2846
'sharp_turn_right_idx' => 31,
2847
'turn_left_idx' => 32,
2848
'turn_right_idx' => 33,
2849
'uturn_left_idx' => 34,
2850
'uturn_right_idx' => 35,
2851
'icon_inv_idx' => 36,
2852
'icon_idx_cnt' => 37,
2853
},
2854
2855
'bike_light_beam_angle_mode' => +{
2856
'_base_type' => FIT_ENUM,
2857
'manual' => 0,
2858
'auto' => 1,
2859
},
2860
2861
'fit_base_unit' => +{
2862
'_base_type' => FIT_UINT16,
2863
'other' => 0,
2864
'kilogram' => 1,
2865
'pound' => 2,
2866
},
2867
2868
'set_type' => +{
2869
'_base_type' => FIT_UINT8,
2870
'rest' => 0,
2871
'active' => 1,
2872
},
2873
2874
'exercise_category' => +{
2875
'_base_type' => FIT_UINT16,
2876
'bench_press' => 0,
2877
'calf_raise' => 1,
2878
'cardio' => 2,
2879
'carry' => 3,
2880
'chop' => 4,
2881
'core' => 5,
2882
'crunch' => 6,
2883
'curl' => 7,
2884
'deadlift' => 8,
2885
'flye' => 9,
2886
'hip_raise' => 10,
2887
'hip_stability' => 11,
2888
'hip_swing' => 12,
2889
'hyperextension' => 13,
2890
'lateral_raise' => 14,
2891
'leg_curl' => 15,
2892
'leg_raise' => 16,
2893
'lunge' => 17,
2894
'olympic_lift' => 18,
2895
'plank' => 19,
2896
'plyo' => 20,
2897
'pull_up' => 21,
2898
'push_up' => 22,
2899
'row' => 23,
2900
'shoulder_press' => 24,
2901
'shoulder_stability' => 25,
2902
'shrug' => 26,
2903
'sit_up' => 27,
2904
'squat' => 28,
2905
'total_body' => 29,
2906
'triceps_extension' => 30,
2907
'warm_up' => 31,
2908
'run' => 32,
2909
'unknown' => 65534,
2910
},
2911
2912
'bench_press_exercise_name' => +{
2913
'_base_type' => FIT_UINT16,
2914
'alternating_dumbbell_chest_press_on_swiss_ball' => 0,
2915
'barbell_bench_press' => 1,
2916
'barbell_board_bench_press' => 2,
2917
'barbell_floor_press' => 3,
2918
'close_grip_barbell_bench_press' => 4,
2919
'decline_dumbbell_bench_press' => 5,
2920
'dumbbell_bench_press' => 6,
2921
'dumbbell_floor_press' => 7,
2922
'incline_barbell_bench_press' => 8,
2923
'incline_dumbbell_bench_press' => 9,
2924
'incline_smith_machine_bench_press' => 10,
2925
'isometric_barbell_bench_press' => 11,
2926
'kettlebell_chest_press' => 12,
2927
'neutral_grip_dumbbell_bench_press' => 13,
2928
'neutral_grip_dumbbell_incline_bench_press' => 14,
2929
'one_arm_floor_press' => 15,
2930
'weighted_one_arm_floor_press' => 16,
2931
'partial_lockout' => 17,
2932
'reverse_grip_barbell_bench_press' => 18,
2933
'reverse_grip_incline_bench_press' => 19,
2934
'single_arm_cable_chest_press' => 20,
2935
'single_arm_dumbbell_bench_press' => 21,
2936
'smith_machine_bench_press' => 22,
2937
'swiss_ball_dumbbell_chest_press' => 23,
2938
'triple_stop_barbell_bench_press' => 24,
2939
'wide_grip_barbell_bench_press' => 25,
2940
'alternating_dumbbell_chest_press' => 26,
2941
},
2942
2943
'calf_raise_exercise_name' => +{
2944
'_base_type' => FIT_UINT16,
2945
'3_way_calf_raise' => 0,
2946
'3_way_weighted_calf_raise' => 1,
2947
'3_way_single_leg_calf_raise' => 2,
2948
'3_way_weighted_single_leg_calf_raise' => 3,
2949
'donkey_calf_raise' => 4,
2950
'weighted_donkey_calf_raise' => 5,
2951
'seated_calf_raise' => 6,
2952
'weighted_seated_calf_raise' => 7,
2953
'seated_dumbbell_toe_raise' => 8,
2954
'single_leg_bent_knee_calf_raise' => 9,
2955
'weighted_single_leg_bent_knee_calf_raise' => 10,
2956
'single_leg_decline_push_up' => 11,
2957
'single_leg_donkey_calf_raise' => 12,
2958
'weighted_single_leg_donkey_calf_raise' => 13,
2959
'single_leg_hip_raise_with_knee_hold' => 14,
2960
'single_leg_standing_calf_raise' => 15,
2961
'single_leg_standing_dumbbell_calf_raise' => 16,
2962
'standing_barbell_calf_raise' => 17,
2963
'standing_calf_raise' => 18,
2964
'weighted_standing_calf_raise' => 19,
2965
'standing_dumbbell_calf_raise' => 20,
2966
},
2967
2968
'cardio_exercise_name' => +{
2969
'_base_type' => FIT_UINT16,
2970
'bob_and_weave_circle' => 0,
2971
'weighted_bob_and_weave_circle' => 1,
2972
'cardio_core_crawl' => 2,
2973
'weighted_cardio_core_crawl' => 3,
2974
'double_under' => 4,
2975
'weighted_double_under' => 5,
2976
'jump_rope' => 6,
2977
'weighted_jump_rope' => 7,
2978
'jump_rope_crossover' => 8,
2979
'weighted_jump_rope_crossover' => 9,
2980
'jump_rope_jog' => 10,
2981
'weighted_jump_rope_jog' => 11,
2982
'jumping_jacks' => 12,
2983
'weighted_jumping_jacks' => 13,
2984
'ski_moguls' => 14,
2985
'weighted_ski_moguls' => 15,
2986
'split_jacks' => 16,
2987
'weighted_split_jacks' => 17,
2988
'squat_jacks' => 18,
2989
'weighted_squat_jacks' => 19,
2990
'triple_under' => 20,
2991
'weighted_triple_under' => 21,
2992
},
2993
2994
'carry_exercise_name' => +{
2995
'_base_type' => FIT_UINT16,
2996
'bar_holds' => 0,
2997
'farmers_walk' => 1,
2998
'farmers_walk_on_toes' => 2,
2999
'hex_dumbbell_hold' => 3,
3000
'overhead_carry' => 4,
3001
},
3002
3003
'chop_exercise_name' => +{
3004
'_base_type' => FIT_UINT16,
3005
'cable_pull_through' => 0,
3006
'cable_rotational_lift' => 1,
3007
'cable_woodchop' => 2,
3008
'cross_chop_to_knee' => 3,
3009
'weighted_cross_chop_to_knee' => 4,
3010
'dumbbell_chop' => 5,
3011
'half_kneeling_rotation' => 6,
3012
'weighted_half_kneeling_rotation' => 7,
3013
'half_kneeling_rotational_chop' => 8,
3014
'half_kneeling_rotational_reverse_chop' => 9,
3015
'half_kneeling_stability_chop' => 10,
3016
'half_kneeling_stability_reverse_chop' => 11,
3017
'kneeling_rotational_chop' => 12,
3018
'kneeling_rotational_reverse_chop' => 13,
3019
'kneeling_stability_chop' => 14,
3020
'kneeling_woodchopper' => 15,
3021
'medicine_ball_wood_chops' => 16,
3022
'power_squat_chops' => 17,
3023
'weighted_power_squat_chops' => 18,
3024
'standing_rotational_chop' => 19,
3025
'standing_split_rotational_chop' => 20,
3026
'standing_split_rotational_reverse_chop' => 21,
3027
'standing_stability_reverse_chop' => 22,
3028
},
3029
3030
'core_exercise_name' => +{
3031
'_base_type' => FIT_UINT16,
3032
'abs_jabs' => 0,
3033
'weighted_abs_jabs' => 1,
3034
'alternating_plate_reach' => 2,
3035
'barbell_rollout' => 3,
3036
'weighted_barbell_rollout' => 4,
3037
'body_bar_oblique_twist' => 5,
3038
'cable_core_press' => 6,
3039
'cable_side_bend' => 7,
3040
'side_bend' => 8,
3041
'weighted_side_bend' => 9,
3042
'crescent_circle' => 10,
3043
'weighted_crescent_circle' => 11,
3044
'cycling_russian_twist' => 12,
3045
'weighted_cycling_russian_twist' => 13,
3046
'elevated_feet_russian_twist' => 14,
3047
'weighted_elevated_feet_russian_twist' => 15,
3048
'half_turkish_get_up' => 16,
3049
'kettlebell_windmill' => 17,
3050
'kneeling_ab_wheel' => 18,
3051
'weighted_kneeling_ab_wheel' => 19,
3052
'modified_front_lever' => 20,
3053
'open_knee_tucks' => 21,
3054
'weighted_open_knee_tucks' => 22,
3055
'side_abs_leg_lift' => 23,
3056
'weighted_side_abs_leg_lift' => 24,
3057
'swiss_ball_jackknife' => 25,
3058
'weighted_swiss_ball_jackknife' => 26,
3059
'swiss_ball_pike' => 27,
3060
'weighted_swiss_ball_pike' => 28,
3061
'swiss_ball_rollout' => 29,
3062
'weighted_swiss_ball_rollout' => 30,
3063
'triangle_hip_press' => 31,
3064
'weighted_triangle_hip_press' => 32,
3065
'trx_suspended_jackknife' => 33,
3066
'weighted_trx_suspended_jackknife' => 34,
3067
'u_boat' => 35,
3068
'weighted_u_boat' => 36,
3069
'windmill_switches' => 37,
3070
'weighted_windmill_switches' => 38,
3071
'alternating_slide_out' => 39,
3072
'weighted_alternating_slide_out' => 40,
3073
'ghd_back_extensions' => 41,
3074
'weighted_ghd_back_extensions' => 42,
3075
'overhead_walk' => 43,
3076
'inchworm' => 44,
3077
'weighted_modified_front_lever' => 45,
3078
'russian_twist' => 46,
3079
'abdominal_leg_rotations' => 47, # Deprecated do not use
3080
'arm_and_leg_extension_on_knees' => 48,
3081
'bicycle' => 49,
3082
'bicep_curl_with_leg_extension' => 50,
3083
'cat_cow' => 51,
3084
'corkscrew' => 52,
3085
'criss_cross' => 53,
3086
'criss_cross_with_ball' => 54, # Deprecated do not use
3087
'double_leg_stretch' => 55,
3088
'knee_folds' => 56,
3089
'lower_lift' => 57,
3090
'neck_pull' => 58,
3091
'pelvic_clocks' => 59,
3092
'roll_over' => 60,
3093
'roll_up' => 61,
3094
'rolling' => 62,
3095
'rowing_1' => 63,
3096
'rowing_2' => 64,
3097
'scissors' => 65,
3098
'single_leg_circles' => 66,
3099
'single_leg_stretch' => 67,
3100
'snake_twist_1_and_2' => 68, # Deprecated do not use
3101
'swan' => 69,
3102
'swimming' => 70,
3103
'teaser' => 71,
3104
'the_hundred' => 72,
3105
},
3106
3107
'crunch_exercise_name' => +{
3108
'_base_type' => FIT_UINT16,
3109
'bicycle_crunch' => 0,
3110
'cable_crunch' => 1,
3111
'circular_arm_crunch' => 2,
3112
'crossed_arms_crunch' => 3,
3113
'weighted_crossed_arms_crunch' => 4,
3114
'cross_leg_reverse_crunch' => 5,
3115
'weighted_cross_leg_reverse_crunch' => 6,
3116
'crunch_chop' => 7,
3117
'weighted_crunch_chop' => 8,
3118
'double_crunch' => 9,
3119
'weighted_double_crunch' => 10,
3120
'elbow_to_knee_crunch' => 11,
3121
'weighted_elbow_to_knee_crunch' => 12,
3122
'flutter_kicks' => 13,
3123
'weighted_flutter_kicks' => 14,
3124
'foam_roller_reverse_crunch_on_bench' => 15,
3125
'weighted_foam_roller_reverse_crunch_on_bench' => 16,
3126
'foam_roller_reverse_crunch_with_dumbbell' => 17,
3127
'foam_roller_reverse_crunch_with_medicine_ball' => 18,
3128
'frog_press' => 19,
3129
'hanging_knee_raise_oblique_crunch' => 20,
3130
'weighted_hanging_knee_raise_oblique_crunch' => 21,
3131
'hip_crossover' => 22,
3132
'weighted_hip_crossover' => 23,
3133
'hollow_rock' => 24,
3134
'weighted_hollow_rock' => 25,
3135
'incline_reverse_crunch' => 26,
3136
'weighted_incline_reverse_crunch' => 27,
3137
'kneeling_cable_crunch' => 28,
3138
'kneeling_cross_crunch' => 29,
3139
'weighted_kneeling_cross_crunch' => 30,
3140
'kneeling_oblique_cable_crunch' => 31,
3141
'knees_to_elbow' => 32,
3142
'leg_extensions' => 33,
3143
'weighted_leg_extensions' => 34,
3144
'leg_levers' => 35,
3145
'mcgill_curl_up' => 36,
3146
'weighted_mcgill_curl_up' => 37,
3147
'modified_pilates_roll_up_with_ball' => 38,
3148
'weighted_modified_pilates_roll_up_with_ball' => 39,
3149
'pilates_crunch' => 40,
3150
'weighted_pilates_crunch' => 41,
3151
'pilates_roll_up_with_ball' => 42,
3152
'weighted_pilates_roll_up_with_ball' => 43,
3153
'raised_legs_crunch' => 44,
3154
'weighted_raised_legs_crunch' => 45,
3155
'reverse_crunch' => 46,
3156
'weighted_reverse_crunch' => 47,
3157
'reverse_crunch_on_a_bench' => 48,
3158
'weighted_reverse_crunch_on_a_bench' => 49,
3159
'reverse_curl_and_lift' => 50,
3160
'weighted_reverse_curl_and_lift' => 51,
3161
'rotational_lift' => 52,
3162
'weighted_rotational_lift' => 53,
3163
'seated_alternating_reverse_crunch' => 54,
3164
'weighted_seated_alternating_reverse_crunch' => 55,
3165
'seated_leg_u' => 56,
3166
'weighted_seated_leg_u' => 57,
3167
'side_to_side_crunch_and_weave' => 58,
3168
'weighted_side_to_side_crunch_and_weave' => 59,
3169
'single_leg_reverse_crunch' => 60,
3170
'weighted_single_leg_reverse_crunch' => 61,
3171
'skater_crunch_cross' => 62,
3172
'weighted_skater_crunch_cross' => 63,
3173
'standing_cable_crunch' => 64,
3174
'standing_side_crunch' => 65,
3175
'step_climb' => 66,
3176
'weighted_step_climb' => 67,
3177
'swiss_ball_crunch' => 68,
3178
'swiss_ball_reverse_crunch' => 69,
3179
'weighted_swiss_ball_reverse_crunch' => 70,
3180
'swiss_ball_russian_twist' => 71,
3181
'weighted_swiss_ball_russian_twist' => 72,
3182
'swiss_ball_side_crunch' => 73,
3183
'weighted_swiss_ball_side_crunch' => 74,
3184
'thoracic_crunches_on_foam_roller' => 75,
3185
'weighted_thoracic_crunches_on_foam_roller' => 76,
3186
'triceps_crunch' => 77,
3187
'weighted_bicycle_crunch' => 78,
3188
'weighted_crunch' => 79,
3189
'weighted_swiss_ball_crunch' => 80,
3190
'toes_to_bar' => 81,
3191
'weighted_toes_to_bar' => 82,
3192
'crunch' => 83,
3193
'straight_leg_crunch_with_ball' => 84,
3194
},
3195
3196
'curl_exercise_name' => +{
3197
'_base_type' => FIT_UINT16,
3198
'alternating_dumbbell_biceps_curl' => 0,
3199
'alternating_dumbbell_biceps_curl_on_swiss_ball' => 1,
3200
'alternating_incline_dumbbell_biceps_curl' => 2,
3201
'barbell_biceps_curl' => 3,
3202
'barbell_reverse_wrist_curl' => 4,
3203
'barbell_wrist_curl' => 5,
3204
'behind_the_back_barbell_reverse_wrist_curl' => 6,
3205
'behind_the_back_one_arm_cable_curl' => 7,
3206
'cable_biceps_curl' => 8,
3207
'cable_hammer_curl' => 9,
3208
'cheating_barbell_biceps_curl' => 10,
3209
'close_grip_ez_bar_biceps_curl' => 11,
3210
'cross_body_dumbbell_hammer_curl' => 12,
3211
'dead_hang_biceps_curl' => 13,
3212
'decline_hammer_curl' => 14,
3213
'dumbbell_biceps_curl_with_static_hold' => 15,
3214
'dumbbell_hammer_curl' => 16,
3215
'dumbbell_reverse_wrist_curl' => 17,
3216
'dumbbell_wrist_curl' => 18,
3217
'ez_bar_preacher_curl' => 19,
3218
'forward_bend_biceps_curl' => 20,
3219
'hammer_curl_to_press' => 21,
3220
'incline_dumbbell_biceps_curl' => 22,
3221
'incline_offset_thumb_dumbbell_curl' => 23,
3222
'kettlebell_biceps_curl' => 24,
3223
'lying_concentration_cable_curl' => 25,
3224
'one_arm_preacher_curl' => 26,
3225
'plate_pinch_curl' => 27,
3226
'preacher_curl_with_cable' => 28,
3227
'reverse_ez_bar_curl' => 29,
3228
'reverse_grip_wrist_curl' => 30,
3229
'reverse_grip_barbell_biceps_curl' => 31,
3230
'seated_alternating_dumbbell_biceps_curl' => 32,
3231
'seated_dumbbell_biceps_curl' => 33,
3232
'seated_reverse_dumbbell_curl' => 34,
3233
'split_stance_offset_pinky_dumbbell_curl' => 35,
3234
'standing_alternating_dumbbell_curls' => 36,
3235
'standing_dumbbell_biceps_curl' => 37,
3236
'standing_ez_bar_biceps_curl' => 38,
3237
'static_curl' => 39,
3238
'swiss_ball_dumbbell_overhead_triceps_extension' => 40,
3239
'swiss_ball_ez_bar_preacher_curl' => 41,
3240
'twisting_standing_dumbbell_biceps_curl' => 42,
3241
'wide_grip_ez_bar_biceps_curl' => 43,
3242
},
3243
3244
'deadlift_exercise_name' => +{
3245
'_base_type' => FIT_UINT16,
3246
'barbell_deadlift' => 0,
3247
'barbell_straight_leg_deadlift' => 1,
3248
'dumbbell_deadlift' => 2,
3249
'dumbbell_single_leg_deadlift_to_row' => 3,
3250
'dumbbell_straight_leg_deadlift' => 4,
3251
'kettlebell_floor_to_shelf' => 5,
3252
'one_arm_one_leg_deadlift' => 6,
3253
'rack_pull' => 7,
3254
'rotational_dumbbell_straight_leg_deadlift' => 8,
3255
'single_arm_deadlift' => 9,
3256
'single_leg_barbell_deadlift' => 10,
3257
'single_leg_barbell_straight_leg_deadlift' => 11,
3258
'single_leg_deadlift_with_barbell' => 12,
3259
'single_leg_rdl_circuit' => 13,
3260
'single_leg_romanian_deadlift_with_dumbbell' => 14,
3261
'sumo_deadlift' => 15,
3262
'sumo_deadlift_high_pull' => 16,
3263
'trap_bar_deadlift' => 17,
3264
'wide_grip_barbell_deadlift' => 18,
3265
},
3266
3267
'flye_exercise_name' => +{
3268
'_base_type' => FIT_UINT16,
3269
'cable_crossover' => 0,
3270
'decline_dumbbell_flye' => 1,
3271
'dumbbell_flye' => 2,
3272
'incline_dumbbell_flye' => 3,
3273
'kettlebell_flye' => 4,
3274
'kneeling_rear_flye' => 5,
3275
'single_arm_standing_cable_reverse_flye' => 6,
3276
'swiss_ball_dumbbell_flye' => 7,
3277
'arm_rotations' => 8,
3278
'hug_a_tree' => 9,
3279
},
3280
3281
'hip_raise_exercise_name' => +{
3282
'_base_type' => FIT_UINT16,
3283
'barbell_hip_thrust_on_floor' => 0,
3284
'barbell_hip_thrust_with_bench' => 1,
3285
'bent_knee_swiss_ball_reverse_hip_raise' => 2,
3286
'weighted_bent_knee_swiss_ball_reverse_hip_raise' => 3,
3287
'bridge_with_leg_extension' => 4,
3288
'weighted_bridge_with_leg_extension' => 5,
3289
'clam_bridge' => 6,
3290
'front_kick_tabletop' => 7,
3291
'weighted_front_kick_tabletop' => 8,
3292
'hip_extension_and_cross' => 9,
3293
'weighted_hip_extension_and_cross' => 10,
3294
'hip_raise' => 11,
3295
'weighted_hip_raise' => 12,
3296
'hip_raise_with_feet_on_swiss_ball' => 13,
3297
'weighted_hip_raise_with_feet_on_swiss_ball' => 14,
3298
'hip_raise_with_head_on_bosu_ball' => 15,
3299
'weighted_hip_raise_with_head_on_bosu_ball' => 16,
3300
'hip_raise_with_head_on_swiss_ball' => 17,
3301
'weighted_hip_raise_with_head_on_swiss_ball' => 18,
3302
'hip_raise_with_knee_squeeze' => 19,
3303
'weighted_hip_raise_with_knee_squeeze' => 20,
3304
'incline_rear_leg_extension' => 21,
3305
'weighted_incline_rear_leg_extension' => 22,
3306
'kettlebell_swing' => 23,
3307
'marching_hip_raise' => 24,
3308
'weighted_marching_hip_raise' => 25,
3309
'marching_hip_raise_with_feet_on_a_swiss_ball' => 26,
3310
'weighted_marching_hip_raise_with_feet_on_a_swiss_ball' => 27,
3311
'reverse_hip_raise' => 28,
3312
'weighted_reverse_hip_raise' => 29,
3313
'single_leg_hip_raise' => 30,
3314
'weighted_single_leg_hip_raise' => 31,
3315
'single_leg_hip_raise_with_foot_on_bench' => 32,
3316
'weighted_single_leg_hip_raise_with_foot_on_bench' => 33,
3317
'single_leg_hip_raise_with_foot_on_bosu_ball' => 34,
3318
'weighted_single_leg_hip_raise_with_foot_on_bosu_ball' => 35,
3319
'single_leg_hip_raise_with_foot_on_foam_roller' => 36,
3320
'weighted_single_leg_hip_raise_with_foot_on_foam_roller' => 37,
3321
'single_leg_hip_raise_with_foot_on_medicine_ball' => 38,
3322
'weighted_single_leg_hip_raise_with_foot_on_medicine_ball' => 39,
3323
'single_leg_hip_raise_with_head_on_bosu_ball' => 40,
3324
'weighted_single_leg_hip_raise_with_head_on_bosu_ball' => 41,
3325
'weighted_clam_bridge' => 42,
3326
'single_leg_swiss_ball_hip_raise_and_leg_curl' => 43,
3327
'clams' => 44,
3328
'inner_thigh_circles' => 45, # Deprecated do not use
3329
'inner_thigh_side_lift' => 46, # Deprecated do not use
3330
'leg_circles' => 47,
3331
'leg_lift' => 48,
3332
'leg_lift_in_external_rotation' => 49,
3333
},
3334
3335
'hip_stability_exercise_name' => +{
3336
'_base_type' => FIT_UINT16,
3337
'band_side_lying_leg_raise' => 0,
3338
'dead_bug' => 1,
3339
'weighted_dead_bug' => 2,
3340
'external_hip_raise' => 3,
3341
'weighted_external_hip_raise' => 4,
3342
'fire_hydrant_kicks' => 5,
3343
'weighted_fire_hydrant_kicks' => 6,
3344
'hip_circles' => 7,
3345
'weighted_hip_circles' => 8,
3346
'inner_thigh_lift' => 9,
3347
'weighted_inner_thigh_lift' => 10,
3348
'lateral_walks_with_band_at_ankles' => 11,
3349
'pretzel_side_kick' => 12,
3350
'weighted_pretzel_side_kick' => 13,
3351
'prone_hip_internal_rotation' => 14,
3352
'weighted_prone_hip_internal_rotation' => 15,
3353
'quadruped' => 16,
3354
'quadruped_hip_extension' => 17,
3355
'weighted_quadruped_hip_extension' => 18,
3356
'quadruped_with_leg_lift' => 19,
3357
'weighted_quadruped_with_leg_lift' => 20,
3358
'side_lying_leg_raise' => 21,
3359
'weighted_side_lying_leg_raise' => 22,
3360
'sliding_hip_adduction' => 23,
3361
'weighted_sliding_hip_adduction' => 24,
3362
'standing_adduction' => 25,
3363
'weighted_standing_adduction' => 26,
3364
'standing_cable_hip_abduction' => 27,
3365
'standing_hip_abduction' => 28,
3366
'weighted_standing_hip_abduction' => 29,
3367
'standing_rear_leg_raise' => 30,
3368
'weighted_standing_rear_leg_raise' => 31,
3369
'supine_hip_internal_rotation' => 32,
3370
'weighted_supine_hip_internal_rotation' => 33,
3371
},
3372
3373
'hip_swing_exercise_name' => +{
3374
'_base_type' => FIT_UINT16,
3375
'single_arm_kettlebell_swing' => 0,
3376
'single_arm_dumbbell_swing' => 1,
3377
'step_out_swing' => 2,
3378
},
3379
3380
'hyperextension_exercise_name' => +{
3381
'_base_type' => FIT_UINT16,
3382
'back_extension_with_opposite_arm_and_leg_reach' => 0,
3383
'weighted_back_extension_with_opposite_arm_and_leg_reach' => 1,
3384
'base_rotations' => 2,
3385
'weighted_base_rotations' => 3,
3386
'bent_knee_reverse_hyperextension' => 4,
3387
'weighted_bent_knee_reverse_hyperextension' => 5,
3388
'hollow_hold_and_roll' => 6,
3389
'weighted_hollow_hold_and_roll' => 7,
3390
'kicks' => 8,
3391
'weighted_kicks' => 9,
3392
'knee_raises' => 10,
3393
'weighted_knee_raises' => 11,
3394
'kneeling_superman' => 12,
3395
'weighted_kneeling_superman' => 13,
3396
'lat_pull_down_with_row' => 14,
3397
'medicine_ball_deadlift_to_reach' => 15,
3398
'one_arm_one_leg_row' => 16,
3399
'one_arm_row_with_band' => 17,
3400
'overhead_lunge_with_medicine_ball' => 18,
3401
'plank_knee_tucks' => 19,
3402
'weighted_plank_knee_tucks' => 20,
3403
'side_step' => 21,
3404
'weighted_side_step' => 22,
3405
'single_leg_back_extension' => 23,
3406
'weighted_single_leg_back_extension' => 24,
3407
'spine_extension' => 25,
3408
'weighted_spine_extension' => 26,
3409
'static_back_extension' => 27,
3410
'weighted_static_back_extension' => 28,
3411
'superman_from_floor' => 29,
3412
'weighted_superman_from_floor' => 30,
3413
'swiss_ball_back_extension' => 31,
3414
'weighted_swiss_ball_back_extension' => 32,
3415
'swiss_ball_hyperextension' => 33,
3416
'weighted_swiss_ball_hyperextension' => 34,
3417
'swiss_ball_opposite_arm_and_leg_lift' => 35,
3418
'weighted_swiss_ball_opposite_arm_and_leg_lift' => 36,
3419
'superman_on_swiss_ball' => 37,
3420
'cobra' => 38,
3421
'supine_floor_barre' => 39, # Deprecated do not use
3422
},
3423
3424
'lateral_raise_exercise_name' => +{
3425
'_base_type' => FIT_UINT16,
3426
'45_degree_cable_external_rotation' => 0,
3427
'alternating_lateral_raise_with_static_hold' => 1,
3428
'bar_muscle_up' => 2,
3429
'bent_over_lateral_raise' => 3,
3430
'cable_diagonal_raise' => 4,
3431
'cable_front_raise' => 5,
3432
'calorie_row' => 6,
3433
'combo_shoulder_raise' => 7,
3434
'dumbbell_diagonal_raise' => 8,
3435
'dumbbell_v_raise' => 9,
3436
'front_raise' => 10,
3437
'leaning_dumbbell_lateral_raise' => 11,
3438
'lying_dumbbell_raise' => 12,
3439
'muscle_up' => 13,
3440
'one_arm_cable_lateral_raise' => 14,
3441
'overhand_grip_rear_lateral_raise' => 15,
3442
'plate_raises' => 16,
3443
'ring_dip' => 17,
3444
'weighted_ring_dip' => 18,
3445
'ring_muscle_up' => 19,
3446
'weighted_ring_muscle_up' => 20,
3447
'rope_climb' => 21,
3448
'weighted_rope_climb' => 22,
3449
'scaption' => 23,
3450
'seated_lateral_raise' => 24,
3451
'seated_rear_lateral_raise' => 25,
3452
'side_lying_lateral_raise' => 26,
3453
'standing_lift' => 27,
3454
'suspended_row' => 28,
3455
'underhand_grip_rear_lateral_raise' => 29,
3456
'wall_slide' => 30,
3457
'weighted_wall_slide' => 31,
3458
'arm_circles' => 32,
3459
'shaving_the_head' => 33,
3460
},
3461
3462
'leg_curl_exercise_name' => +{
3463
'_base_type' => FIT_UINT16,
3464
'leg_curl' => 0,
3465
'weighted_leg_curl' => 1,
3466
'good_morning' => 2,
3467
'seated_barbell_good_morning' => 3,
3468
'single_leg_barbell_good_morning' => 4,
3469
'single_leg_sliding_leg_curl' => 5,
3470
'sliding_leg_curl' => 6,
3471
'split_barbell_good_morning' => 7,
3472
'split_stance_extension' => 8,
3473
'staggered_stance_good_morning' => 9,
3474
'swiss_ball_hip_raise_and_leg_curl' => 10,
3475
'zercher_good_morning' => 11,
3476
},
3477
3478
'leg_raise_exercise_name' => +{
3479
'_base_type' => FIT_UINT16,
3480
'hanging_knee_raise' => 0,
3481
'hanging_leg_raise' => 1,
3482
'weighted_hanging_leg_raise' => 2,
3483
'hanging_single_leg_raise' => 3,
3484
'weighted_hanging_single_leg_raise' => 4,
3485
'kettlebell_leg_raises' => 5,
3486
'leg_lowering_drill' => 6,
3487
'weighted_leg_lowering_drill' => 7,
3488
'lying_straight_leg_raise' => 8,
3489
'weighted_lying_straight_leg_raise' => 9,
3490
'medicine_ball_leg_drops' => 10,
3491
'quadruped_leg_raise' => 11,
3492
'weighted_quadruped_leg_raise' => 12,
3493
'reverse_leg_raise' => 13,
3494
'weighted_reverse_leg_raise' => 14,
3495
'reverse_leg_raise_on_swiss_ball' => 15,
3496
'weighted_reverse_leg_raise_on_swiss_ball' => 16,
3497
'single_leg_lowering_drill' => 17,
3498
'weighted_single_leg_lowering_drill' => 18,
3499
'weighted_hanging_knee_raise' => 19,
3500
'lateral_stepover' => 20,
3501
'weighted_lateral_stepover' => 21,
3502
},
3503
3504
'lunge_exercise_name' => +{
3505
'_base_type' => FIT_UINT16,
3506
'overhead_lunge' => 0,
3507
'lunge_matrix' => 1,
3508
'weighted_lunge_matrix' => 2,
3509
'alternating_barbell_forward_lunge' => 3,
3510
'alternating_dumbbell_lunge_with_reach' => 4,
3511
'back_foot_elevated_dumbbell_split_squat' => 5,
3512
'barbell_box_lunge' => 6,
3513
'barbell_bulgarian_split_squat' => 7,
3514
'barbell_crossover_lunge' => 8,
3515
'barbell_front_split_squat' => 9,
3516
'barbell_lunge' => 10,
3517
'barbell_reverse_lunge' => 11,
3518
'barbell_side_lunge' => 12,
3519
'barbell_split_squat' => 13,
3520
'core_control_rear_lunge' => 14,
3521
'diagonal_lunge' => 15,
3522
'drop_lunge' => 16,
3523
'dumbbell_box_lunge' => 17,
3524
'dumbbell_bulgarian_split_squat' => 18,
3525
'dumbbell_crossover_lunge' => 19,
3526
'dumbbell_diagonal_lunge' => 20,
3527
'dumbbell_lunge' => 21,
3528
'dumbbell_lunge_and_rotation' => 22,
3529
'dumbbell_overhead_bulgarian_split_squat' => 23,
3530
'dumbbell_reverse_lunge_to_high_knee_and_press' => 24,
3531
'dumbbell_side_lunge' => 25,
3532
'elevated_front_foot_barbell_split_squat' => 26,
3533
'front_foot_elevated_dumbbell_split_squat' => 27,
3534
'gunslinger_lunge' => 28,
3535
'lawnmower_lunge' => 29,
3536
'low_lunge_with_isometric_adduction' => 30,
3537
'low_side_to_side_lunge' => 31,
3538
'lunge' => 32,
3539
'weighted_lunge' => 33,
3540
'lunge_with_arm_reach' => 34,
3541
'lunge_with_diagonal_reach' => 35,
3542
'lunge_with_side_bend' => 36,
3543
'offset_dumbbell_lunge' => 37,
3544
'offset_dumbbell_reverse_lunge' => 38,
3545
'overhead_bulgarian_split_squat' => 39,
3546
'overhead_dumbbell_reverse_lunge' => 40,
3547
'overhead_dumbbell_split_squat' => 41,
3548
'overhead_lunge_with_rotation' => 42,
3549
'reverse_barbell_box_lunge' => 43,
3550
'reverse_box_lunge' => 44,
3551
'reverse_dumbbell_box_lunge' => 45,
3552
'reverse_dumbbell_crossover_lunge' => 46,
3553
'reverse_dumbbell_diagonal_lunge' => 47,
3554
'reverse_lunge_with_reach_back' => 48,
3555
'weighted_reverse_lunge_with_reach_back' => 49,
3556
'reverse_lunge_with_twist_and_overhead_reach' => 50,
3557
'weighted_reverse_lunge_with_twist_and_overhead_reach' => 51,
3558
'reverse_sliding_box_lunge' => 52,
3559
'weighted_reverse_sliding_box_lunge' => 53,
3560
'reverse_sliding_lunge' => 54,
3561
'weighted_reverse_sliding_lunge' => 55,
3562
'runners_lunge_to_balance' => 56,
3563
'weighted_runners_lunge_to_balance' => 57,
3564
'shifting_side_lunge' => 58,
3565
'side_and_crossover_lunge' => 59,
3566
'weighted_side_and_crossover_lunge' => 60,
3567
'side_lunge' => 61,
3568
'weighted_side_lunge' => 62,
3569
'side_lunge_and_press' => 63,
3570
'side_lunge_jump_off' => 64,
3571
'side_lunge_sweep' => 65,
3572
'weighted_side_lunge_sweep' => 66,
3573
'side_lunge_to_crossover_tap' => 67,
3574
'weighted_side_lunge_to_crossover_tap' => 68,
3575
'side_to_side_lunge_chops' => 69,
3576
'weighted_side_to_side_lunge_chops' => 70,
3577
'siff_jump_lunge' => 71,
3578
'weighted_siff_jump_lunge' => 72,
3579
'single_arm_reverse_lunge_and_press' => 73,
3580
'sliding_lateral_lunge' => 74,
3581
'weighted_sliding_lateral_lunge' => 75,
3582
'walking_barbell_lunge' => 76,
3583
'walking_dumbbell_lunge' => 77,
3584
'walking_lunge' => 78,
3585
'weighted_walking_lunge' => 79,
3586
'wide_grip_overhead_barbell_split_squat' => 80,
3587
},
3588
3589
'olympic_lift_exercise_name' => +{
3590
'_base_type' => FIT_UINT16,
3591
'barbell_hang_power_clean' => 0,
3592
'barbell_hang_squat_clean' => 1,
3593
'barbell_power_clean' => 2,
3594
'barbell_power_snatch' => 3,
3595
'barbell_squat_clean' => 4,
3596
'clean_and_jerk' => 5,
3597
'barbell_hang_power_snatch' => 6,
3598
'barbell_hang_pull' => 7,
3599
'barbell_high_pull' => 8,
3600
'barbell_snatch' => 9,
3601
'barbell_split_jerk' => 10,
3602
'clean' => 11,
3603
'dumbbell_clean' => 12,
3604
'dumbbell_hang_pull' => 13,
3605
'one_hand_dumbbell_split_snatch' => 14,
3606
'push_jerk' => 15,
3607
'single_arm_dumbbell_snatch' => 16,
3608
'single_arm_hang_snatch' => 17,
3609
'single_arm_kettlebell_snatch' => 18,
3610
'split_jerk' => 19,
3611
'squat_clean_and_jerk' => 20,
3612
},
3613
3614
'plank_exercise_name' => +{
3615
'_base_type' => FIT_UINT16,
3616
'45_degree_plank' => 0,
3617
'weighted_45_degree_plank' => 1,
3618
'90_degree_static_hold' => 2,
3619
'weighted_90_degree_static_hold' => 3,
3620
'bear_crawl' => 4,
3621
'weighted_bear_crawl' => 5,
3622
'cross_body_mountain_climber' => 6,
3623
'weighted_cross_body_mountain_climber' => 7,
3624
'elbow_plank_pike_jacks' => 8,
3625
'weighted_elbow_plank_pike_jacks' => 9,
3626
'elevated_feet_plank' => 10,
3627
'weighted_elevated_feet_plank' => 11,
3628
'elevator_abs' => 12,
3629
'weighted_elevator_abs' => 13,
3630
'extended_plank' => 14,
3631
'weighted_extended_plank' => 15,
3632
'full_plank_passe_twist' => 16,
3633
'weighted_full_plank_passe_twist' => 17,
3634
'inching_elbow_plank' => 18,
3635
'weighted_inching_elbow_plank' => 19,
3636
'inchworm_to_side_plank' => 20,
3637
'weighted_inchworm_to_side_plank' => 21,
3638
'kneeling_plank' => 22,
3639
'weighted_kneeling_plank' => 23,
3640
'kneeling_side_plank_with_leg_lift' => 24,
3641
'weighted_kneeling_side_plank_with_leg_lift' => 25,
3642
'lateral_roll' => 26,
3643
'weighted_lateral_roll' => 27,
3644
'lying_reverse_plank' => 28,
3645
'weighted_lying_reverse_plank' => 29,
3646
'medicine_ball_mountain_climber' => 30,
3647
'weighted_medicine_ball_mountain_climber' => 31,
3648
'modified_mountain_climber_and_extension' => 32,
3649
'weighted_modified_mountain_climber_and_extension' => 33,
3650
'mountain_climber' => 34,
3651
'weighted_mountain_climber' => 35,
3652
'mountain_climber_on_sliding_discs' => 36,
3653
'weighted_mountain_climber_on_sliding_discs' => 37,
3654
'mountain_climber_with_feet_on_bosu_ball' => 38,
3655
'weighted_mountain_climber_with_feet_on_bosu_ball' => 39,
3656
'mountain_climber_with_hands_on_bench' => 40,
3657
'mountain_climber_with_hands_on_swiss_ball' => 41,
3658
'weighted_mountain_climber_with_hands_on_swiss_ball' => 42,
3659
'plank' => 43,
3660
'plank_jacks_with_feet_on_sliding_discs' => 44,
3661
'weighted_plank_jacks_with_feet_on_sliding_discs' => 45,
3662
'plank_knee_twist' => 46,
3663
'weighted_plank_knee_twist' => 47,
3664
'plank_pike_jumps' => 48,
3665
'weighted_plank_pike_jumps' => 49,
3666
'plank_pikes' => 50,
3667
'weighted_plank_pikes' => 51,
3668
'plank_to_stand_up' => 52,
3669
'weighted_plank_to_stand_up' => 53,
3670
'plank_with_arm_raise' => 54,
3671
'weighted_plank_with_arm_raise' => 55,
3672
'plank_with_knee_to_elbow' => 56,
3673
'weighted_plank_with_knee_to_elbow' => 57,
3674
'plank_with_oblique_crunch' => 58,
3675
'weighted_plank_with_oblique_crunch' => 59,
3676
'plyometric_side_plank' => 60,
3677
'weighted_plyometric_side_plank' => 61,
3678
'rolling_side_plank' => 62,
3679
'weighted_rolling_side_plank' => 63,
3680
'side_kick_plank' => 64,
3681
'weighted_side_kick_plank' => 65,
3682
'side_plank' => 66,
3683
'weighted_side_plank' => 67,
3684
'side_plank_and_row' => 68,
3685
'weighted_side_plank_and_row' => 69,
3686
'side_plank_lift' => 70,
3687
'weighted_side_plank_lift' => 71,
3688
'side_plank_with_elbow_on_bosu_ball' => 72,
3689
'weighted_side_plank_with_elbow_on_bosu_ball' => 73,
3690
'side_plank_with_feet_on_bench' => 74,
3691
'weighted_side_plank_with_feet_on_bench' => 75,
3692
'side_plank_with_knee_circle' => 76,
3693
'weighted_side_plank_with_knee_circle' => 77,
3694
'side_plank_with_knee_tuck' => 78,
3695
'weighted_side_plank_with_knee_tuck' => 79,
3696
'side_plank_with_leg_lift' => 80,
3697
'weighted_side_plank_with_leg_lift' => 81,
3698
'side_plank_with_reach_under' => 82,
3699
'weighted_side_plank_with_reach_under' => 83,
3700
'single_leg_elevated_feet_plank' => 84,
3701
'weighted_single_leg_elevated_feet_plank' => 85,
3702
'single_leg_flex_and_extend' => 86,
3703
'weighted_single_leg_flex_and_extend' => 87,
3704
'single_leg_side_plank' => 88,
3705
'weighted_single_leg_side_plank' => 89,
3706
'spiderman_plank' => 90,
3707
'weighted_spiderman_plank' => 91,
3708
'straight_arm_plank' => 92,
3709
'weighted_straight_arm_plank' => 93,
3710
'straight_arm_plank_with_shoulder_touch' => 94,
3711
'weighted_straight_arm_plank_with_shoulder_touch' => 95,
3712
'swiss_ball_plank' => 96,
3713
'weighted_swiss_ball_plank' => 97,
3714
'swiss_ball_plank_leg_lift' => 98,
3715
'weighted_swiss_ball_plank_leg_lift' => 99,
3716
'swiss_ball_plank_leg_lift_and_hold' => 100,
3717
'swiss_ball_plank_with_feet_on_bench' => 101,
3718
'weighted_swiss_ball_plank_with_feet_on_bench' => 102,
3719
'swiss_ball_prone_jackknife' => 103,
3720
'weighted_swiss_ball_prone_jackknife' => 104,
3721
'swiss_ball_side_plank' => 105,
3722
'weighted_swiss_ball_side_plank' => 106,
3723
'three_way_plank' => 107,
3724
'weighted_three_way_plank' => 108,
3725
'towel_plank_and_knee_in' => 109,
3726
'weighted_towel_plank_and_knee_in' => 110,
3727
't_stabilization' => 111,
3728
'weighted_t_stabilization' => 112,
3729
'turkish_get_up_to_side_plank' => 113,
3730
'weighted_turkish_get_up_to_side_plank' => 114,
3731
'two_point_plank' => 115,
3732
'weighted_two_point_plank' => 116,
3733
'weighted_plank' => 117,
3734
'wide_stance_plank_with_diagonal_arm_lift' => 118,
3735
'weighted_wide_stance_plank_with_diagonal_arm_lift' => 119,
3736
'wide_stance_plank_with_diagonal_leg_lift' => 120,
3737
'weighted_wide_stance_plank_with_diagonal_leg_lift' => 121,
3738
'wide_stance_plank_with_leg_lift' => 122,
3739
'weighted_wide_stance_plank_with_leg_lift' => 123,
3740
'wide_stance_plank_with_opposite_arm_and_leg_lift' => 124,
3741
'weighted_mountain_climber_with_hands_on_bench' => 125,
3742
'weighted_swiss_ball_plank_leg_lift_and_hold' => 126,
3743
'weighted_wide_stance_plank_with_opposite_arm_and_leg_lift' => 127,
3744
'plank_with_feet_on_swiss_ball' => 128,
3745
'side_plank_to_plank_with_reach_under' => 129,
3746
'bridge_with_glute_lower_lift' => 130,
3747
'bridge_one_leg_bridge' => 131,
3748
'plank_with_arm_variations' => 132,
3749
'plank_with_leg_lift' => 133,
3750
'reverse_plank_with_leg_pull' => 134,
3751
},
3752
3753
'plyo_exercise_name' => +{
3754
'_base_type' => FIT_UINT16,
3755
'alternating_jump_lunge' => 0,
3756
'weighted_alternating_jump_lunge' => 1,
3757
'barbell_jump_squat' => 2,
3758
'body_weight_jump_squat' => 3,
3759
'weighted_jump_squat' => 4,
3760
'cross_knee_strike' => 5,
3761
'weighted_cross_knee_strike' => 6,
3762
'depth_jump' => 7,
3763
'weighted_depth_jump' => 8,
3764
'dumbbell_jump_squat' => 9,
3765
'dumbbell_split_jump' => 10,
3766
'front_knee_strike' => 11,
3767
'weighted_front_knee_strike' => 12,
3768
'high_box_jump' => 13,
3769
'weighted_high_box_jump' => 14,
3770
'isometric_explosive_body_weight_jump_squat' => 15,
3771
'weighted_isometric_explosive_jump_squat' => 16,
3772
'lateral_leap_and_hop' => 17,
3773
'weighted_lateral_leap_and_hop' => 18,
3774
'lateral_plyo_squats' => 19,
3775
'weighted_lateral_plyo_squats' => 20,
3776
'lateral_slide' => 21,
3777
'weighted_lateral_slide' => 22,
3778
'medicine_ball_overhead_throws' => 23,
3779
'medicine_ball_side_throw' => 24,
3780
'medicine_ball_slam' => 25,
3781
'side_to_side_medicine_ball_throws' => 26,
3782
'side_to_side_shuffle_jump' => 27,
3783
'weighted_side_to_side_shuffle_jump' => 28,
3784
'squat_jump_onto_box' => 29,
3785
'weighted_squat_jump_onto_box' => 30,
3786
'squat_jumps_in_and_out' => 31,
3787
'weighted_squat_jumps_in_and_out' => 32,
3788
},
3789
3790
'pull_up_exercise_name' => +{
3791
'_base_type' => FIT_UINT16,
3792
'banded_pull_ups' => 0,
3793
'30_degree_lat_pulldown' => 1,
3794
'band_assisted_chin_up' => 2,
3795
'close_grip_chin_up' => 3,
3796
'weighted_close_grip_chin_up' => 4,
3797
'close_grip_lat_pulldown' => 5,
3798
'crossover_chin_up' => 6,
3799
'weighted_crossover_chin_up' => 7,
3800
'ez_bar_pullover' => 8,
3801
'hanging_hurdle' => 9,
3802
'weighted_hanging_hurdle' => 10,
3803
'kneeling_lat_pulldown' => 11,
3804
'kneeling_underhand_grip_lat_pulldown' => 12,
3805
'lat_pulldown' => 13,
3806
'mixed_grip_chin_up' => 14,
3807
'weighted_mixed_grip_chin_up' => 15,
3808
'mixed_grip_pull_up' => 16,
3809
'weighted_mixed_grip_pull_up' => 17,
3810
'reverse_grip_pulldown' => 18,
3811
'standing_cable_pullover' => 19,
3812
'straight_arm_pulldown' => 20,
3813
'swiss_ball_ez_bar_pullover' => 21,
3814
'towel_pull_up' => 22,
3815
'weighted_towel_pull_up' => 23,
3816
'weighted_pull_up' => 24,
3817
'wide_grip_lat_pulldown' => 25,
3818
'wide_grip_pull_up' => 26,
3819
'weighted_wide_grip_pull_up' => 27,
3820
'burpee_pull_up' => 28,
3821
'weighted_burpee_pull_up' => 29,
3822
'jumping_pull_ups' => 30,
3823
'weighted_jumping_pull_ups' => 31,
3824
'kipping_pull_up' => 32,
3825
'weighted_kipping_pull_up' => 33,
3826
'l_pull_up' => 34,
3827
'weighted_l_pull_up' => 35,
3828
'suspended_chin_up' => 36,
3829
'weighted_suspended_chin_up' => 37,
3830
'pull_up' => 38,
3831
},
3832
3833
'push_up_exercise_name' => +{
3834
'_base_type' => FIT_UINT16,
3835
'chest_press_with_band' => 0,
3836
'alternating_staggered_push_up' => 1,
3837
'weighted_alternating_staggered_push_up' => 2,
3838
'alternating_hands_medicine_ball_push_up' => 3,
3839
'weighted_alternating_hands_medicine_ball_push_up' => 4,
3840
'bosu_ball_push_up' => 5,
3841
'weighted_bosu_ball_push_up' => 6,
3842
'clapping_push_up' => 7,
3843
'weighted_clapping_push_up' => 8,
3844
'close_grip_medicine_ball_push_up' => 9,
3845
'weighted_close_grip_medicine_ball_push_up' => 10,
3846
'close_hands_push_up' => 11,
3847
'weighted_close_hands_push_up' => 12,
3848
'decline_push_up' => 13,
3849
'weighted_decline_push_up' => 14,
3850
'diamond_push_up' => 15,
3851
'weighted_diamond_push_up' => 16,
3852
'explosive_crossover_push_up' => 17,
3853
'weighted_explosive_crossover_push_up' => 18,
3854
'explosive_push_up' => 19,
3855
'weighted_explosive_push_up' => 20,
3856
'feet_elevated_side_to_side_push_up' => 21,
3857
'weighted_feet_elevated_side_to_side_push_up' => 22,
3858
'hand_release_push_up' => 23,
3859
'weighted_hand_release_push_up' => 24,
3860
'handstand_push_up' => 25,
3861
'weighted_handstand_push_up' => 26,
3862
'incline_push_up' => 27,
3863
'weighted_incline_push_up' => 28,
3864
'isometric_explosive_push_up' => 29,
3865
'weighted_isometric_explosive_push_up' => 30,
3866
'judo_push_up' => 31,
3867
'weighted_judo_push_up' => 32,
3868
'kneeling_push_up' => 33,
3869
'weighted_kneeling_push_up' => 34,
3870
'medicine_ball_chest_pass' => 35,
3871
'medicine_ball_push_up' => 36,
3872
'weighted_medicine_ball_push_up' => 37,
3873
'one_arm_push_up' => 38,
3874
'weighted_one_arm_push_up' => 39,
3875
'weighted_push_up' => 40,
3876
'push_up_and_row' => 41,
3877
'weighted_push_up_and_row' => 42,
3878
'push_up_plus' => 43,
3879
'weighted_push_up_plus' => 44,
3880
'push_up_with_feet_on_swiss_ball' => 45,
3881
'weighted_push_up_with_feet_on_swiss_ball' => 46,
3882
'push_up_with_one_hand_on_medicine_ball' => 47,
3883
'weighted_push_up_with_one_hand_on_medicine_ball' => 48,
3884
'shoulder_push_up' => 49,
3885
'weighted_shoulder_push_up' => 50,
3886
'single_arm_medicine_ball_push_up' => 51,
3887
'weighted_single_arm_medicine_ball_push_up' => 52,
3888
'spiderman_push_up' => 53,
3889
'weighted_spiderman_push_up' => 54,
3890
'stacked_feet_push_up' => 55,
3891
'weighted_stacked_feet_push_up' => 56,
3892
'staggered_hands_push_up' => 57,
3893
'weighted_staggered_hands_push_up' => 58,
3894
'suspended_push_up' => 59,
3895
'weighted_suspended_push_up' => 60,
3896
'swiss_ball_push_up' => 61,
3897
'weighted_swiss_ball_push_up' => 62,
3898
'swiss_ball_push_up_plus' => 63,
3899
'weighted_swiss_ball_push_up_plus' => 64,
3900
't_push_up' => 65,
3901
'weighted_t_push_up' => 66,
3902
'triple_stop_push_up' => 67,
3903
'weighted_triple_stop_push_up' => 68,
3904
'wide_hands_push_up' => 69,
3905
'weighted_wide_hands_push_up' => 70,
3906
'parallette_handstand_push_up' => 71,
3907
'weighted_parallette_handstand_push_up' => 72,
3908
'ring_handstand_push_up' => 73,
3909
'weighted_ring_handstand_push_up' => 74,
3910
'ring_push_up' => 75,
3911
'weighted_ring_push_up' => 76,
3912
'push_up' => 77,
3913
'pilates_pushup' => 78,
3914
},
3915
3916
'row_exercise_name' => +{
3917
'_base_type' => FIT_UINT16,
3918
'barbell_straight_leg_deadlift_to_row' => 0,
3919
'cable_row_standing' => 1,
3920
'dumbbell_row' => 2,
3921
'elevated_feet_inverted_row' => 3,
3922
'weighted_elevated_feet_inverted_row' => 4,
3923
'face_pull' => 5,
3924
'face_pull_with_external_rotation' => 6,
3925
'inverted_row_with_feet_on_swiss_ball' => 7,
3926
'weighted_inverted_row_with_feet_on_swiss_ball' => 8,
3927
'kettlebell_row' => 9,
3928
'modified_inverted_row' => 10,
3929
'weighted_modified_inverted_row' => 11,
3930
'neutral_grip_alternating_dumbbell_row' => 12,
3931
'one_arm_bent_over_row' => 13,
3932
'one_legged_dumbbell_row' => 14,
3933
'renegade_row' => 15,
3934
'reverse_grip_barbell_row' => 16,
3935
'rope_handle_cable_row' => 17,
3936
'seated_cable_row' => 18,
3937
'seated_dumbbell_row' => 19,
3938
'single_arm_cable_row' => 20,
3939
'single_arm_cable_row_and_rotation' => 21,
3940
'single_arm_inverted_row' => 22,
3941
'weighted_single_arm_inverted_row' => 23,
3942
'single_arm_neutral_grip_dumbbell_row' => 24,
3943
'single_arm_neutral_grip_dumbbell_row_and_rotation' => 25,
3944
'suspended_inverted_row' => 26,
3945
'weighted_suspended_inverted_row' => 27,
3946
't_bar_row' => 28,
3947
'towel_grip_inverted_row' => 29,
3948
'weighted_towel_grip_inverted_row' => 30,
3949
'underhand_grip_cable_row' => 31,
3950
'v_grip_cable_row' => 32,
3951
'wide_grip_seated_cable_row' => 33,
3952
},
3953
3954
'shoulder_press_exercise_name' => +{
3955
'_base_type' => FIT_UINT16,
3956
'alternating_dumbbell_shoulder_press' => 0,
3957
'arnold_press' => 1,
3958
'barbell_front_squat_to_push_press' => 2,
3959
'barbell_push_press' => 3,
3960
'barbell_shoulder_press' => 4,
3961
'dead_curl_press' => 5,
3962
'dumbbell_alternating_shoulder_press_and_twist' => 6,
3963
'dumbbell_hammer_curl_to_lunge_to_press' => 7,
3964
'dumbbell_push_press' => 8,
3965
'floor_inverted_shoulder_press' => 9,
3966
'weighted_floor_inverted_shoulder_press' => 10,
3967
'inverted_shoulder_press' => 11,
3968
'weighted_inverted_shoulder_press' => 12,
3969
'one_arm_push_press' => 13,
3970
'overhead_barbell_press' => 14,
3971
'overhead_dumbbell_press' => 15,
3972
'seated_barbell_shoulder_press' => 16,
3973
'seated_dumbbell_shoulder_press' => 17,
3974
'single_arm_dumbbell_shoulder_press' => 18,
3975
'single_arm_step_up_and_press' => 19,
3976
'smith_machine_overhead_press' => 20,
3977
'split_stance_hammer_curl_to_press' => 21,
3978
'swiss_ball_dumbbell_shoulder_press' => 22,
3979
'weight_plate_front_raise' => 23,
3980
},
3981
3982
'shoulder_stability_exercise_name' => +{
3983
'_base_type' => FIT_UINT16,
3984
'90_degree_cable_external_rotation' => 0,
3985
'band_external_rotation' => 1,
3986
'band_internal_rotation' => 2,
3987
'bent_arm_lateral_raise_and_external_rotation' => 3,
3988
'cable_external_rotation' => 4,
3989
'dumbbell_face_pull_with_external_rotation' => 5,
3990
'floor_i_raise' => 6,
3991
'weighted_floor_i_raise' => 7,
3992
'floor_t_raise' => 8,
3993
'weighted_floor_t_raise' => 9,
3994
'floor_y_raise' => 10,
3995
'weighted_floor_y_raise' => 11,
3996
'incline_i_raise' => 12,
3997
'weighted_incline_i_raise' => 13,
3998
'incline_l_raise' => 14,
3999
'weighted_incline_l_raise' => 15,
4000
'incline_t_raise' => 16,
4001
'weighted_incline_t_raise' => 17,
4002
'incline_w_raise' => 18,
4003
'weighted_incline_w_raise' => 19,
4004
'incline_y_raise' => 20,
4005
'weighted_incline_y_raise' => 21,
4006
'lying_external_rotation' => 22,
4007
'seated_dumbbell_external_rotation' => 23,
4008
'standing_l_raise' => 24,
4009
'swiss_ball_i_raise' => 25,
4010
'weighted_swiss_ball_i_raise' => 26,
4011
'swiss_ball_t_raise' => 27,
4012
'weighted_swiss_ball_t_raise' => 28,
4013
'swiss_ball_w_raise' => 29,
4014
'weighted_swiss_ball_w_raise' => 30,
4015
'swiss_ball_y_raise' => 31,
4016
'weighted_swiss_ball_y_raise' => 32,
4017
},
4018
4019
'shrug_exercise_name' => +{
4020
'_base_type' => FIT_UINT16,
4021
'barbell_jump_shrug' => 0,
4022
'barbell_shrug' => 1,
4023
'barbell_upright_row' => 2,
4024
'behind_the_back_smith_machine_shrug' => 3,
4025
'dumbbell_jump_shrug' => 4,
4026
'dumbbell_shrug' => 5,
4027
'dumbbell_upright_row' => 6,
4028
'incline_dumbbell_shrug' => 7,
4029
'overhead_barbell_shrug' => 8,
4030
'overhead_dumbbell_shrug' => 9,
4031
'scaption_and_shrug' => 10,
4032
'scapular_retraction' => 11,
4033
'serratus_chair_shrug' => 12,
4034
'weighted_serratus_chair_shrug' => 13,
4035
'serratus_shrug' => 14,
4036
'weighted_serratus_shrug' => 15,
4037
'wide_grip_jump_shrug' => 16,
4038
},
4039
4040
'sit_up_exercise_name' => +{
4041
'_base_type' => FIT_UINT16,
4042
'alternating_sit_up' => 0,
4043
'weighted_alternating_sit_up' => 1,
4044
'bent_knee_v_up' => 2,
4045
'weighted_bent_knee_v_up' => 3,
4046
'butterfly_sit_up' => 4,
4047
'weighted_butterfly_situp' => 5,
4048
'cross_punch_roll_up' => 6,
4049
'weighted_cross_punch_roll_up' => 7,
4050
'crossed_arms_sit_up' => 8,
4051
'weighted_crossed_arms_sit_up' => 9,
4052
'get_up_sit_up' => 10,
4053
'weighted_get_up_sit_up' => 11,
4054
'hovering_sit_up' => 12,
4055
'weighted_hovering_sit_up' => 13,
4056
'kettlebell_sit_up' => 14,
4057
'medicine_ball_alternating_v_up' => 15,
4058
'medicine_ball_sit_up' => 16,
4059
'medicine_ball_v_up' => 17,
4060
'modified_sit_up' => 18,
4061
'negative_sit_up' => 19,
4062
'one_arm_full_sit_up' => 20,
4063
'reclining_circle' => 21,
4064
'weighted_reclining_circle' => 22,
4065
'reverse_curl_up' => 23,
4066
'weighted_reverse_curl_up' => 24,
4067
'single_leg_swiss_ball_jackknife' => 25,
4068
'weighted_single_leg_swiss_ball_jackknife' => 26,
4069
'the_teaser' => 27,
4070
'the_teaser_weighted' => 28,
4071
'three_part_roll_down' => 29,
4072
'weighted_three_part_roll_down' => 30,
4073
'v_up' => 31,
4074
'weighted_v_up' => 32,
4075
'weighted_russian_twist_on_swiss_ball' => 33,
4076
'weighted_sit_up' => 34,
4077
'x_abs' => 35,
4078
'weighted_x_abs' => 36,
4079
'sit_up' => 37,
4080
},
4081
4082
'squat_exercise_name' => +{
4083
'_base_type' => FIT_UINT16,
4084
'leg_press' => 0,
4085
'back_squat_with_body_bar' => 1,
4086
'back_squats' => 2,
4087
'weighted_back_squats' => 3,
4088
'balancing_squat' => 4,
4089
'weighted_balancing_squat' => 5,
4090
'barbell_back_squat' => 6,
4091
'barbell_box_squat' => 7,
4092
'barbell_front_squat' => 8,
4093
'barbell_hack_squat' => 9,
4094
'barbell_hang_squat_snatch' => 10,
4095
'barbell_lateral_step_up' => 11,
4096
'barbell_quarter_squat' => 12,
4097
'barbell_siff_squat' => 13,
4098
'barbell_squat_snatch' => 14,
4099
'barbell_squat_with_heels_raised' => 15,
4100
'barbell_stepover' => 16,
4101
'barbell_step_up' => 17,
4102
'bench_squat_with_rotational_chop' => 18,
4103
'weighted_bench_squat_with_rotational_chop' => 19,
4104
'body_weight_wall_squat' => 20,
4105
'weighted_wall_squat' => 21,
4106
'box_step_squat' => 22,
4107
'weighted_box_step_squat' => 23,
4108
'braced_squat' => 24,
4109
'crossed_arm_barbell_front_squat' => 25,
4110
'crossover_dumbbell_step_up' => 26,
4111
'dumbbell_front_squat' => 27,
4112
'dumbbell_split_squat' => 28,
4113
'dumbbell_squat' => 29,
4114
'dumbbell_squat_clean' => 30,
4115
'dumbbell_stepover' => 31,
4116
'dumbbell_step_up' => 32,
4117
'elevated_single_leg_squat' => 33,
4118
'weighted_elevated_single_leg_squat' => 34,
4119
'figure_four_squats' => 35,
4120
'weighted_figure_four_squats' => 36,
4121
'goblet_squat' => 37,
4122
'kettlebell_squat' => 38,
4123
'kettlebell_swing_overhead' => 39,
4124
'kettlebell_swing_with_flip_to_squat' => 40,
4125
'lateral_dumbbell_step_up' => 41,
4126
'one_legged_squat' => 42,
4127
'overhead_dumbbell_squat' => 43,
4128
'overhead_squat' => 44,
4129
'partial_single_leg_squat' => 45,
4130
'weighted_partial_single_leg_squat' => 46,
4131
'pistol_squat' => 47,
4132
'weighted_pistol_squat' => 48,
4133
'plie_slides' => 49,
4134
'weighted_plie_slides' => 50,
4135
'plie_squat' => 51,
4136
'weighted_plie_squat' => 52,
4137
'prisoner_squat' => 53,
4138
'weighted_prisoner_squat' => 54,
4139
'single_leg_bench_get_up' => 55,
4140
'weighted_single_leg_bench_get_up' => 56,
4141
'single_leg_bench_squat' => 57,
4142
'weighted_single_leg_bench_squat' => 58,
4143
'single_leg_squat_on_swiss_ball' => 59,
4144
'weighted_single_leg_squat_on_swiss_ball' => 60,
4145
'squat' => 61,
4146
'weighted_squat' => 62,
4147
'squats_with_band' => 63,
4148
'staggered_squat' => 64,
4149
'weighted_staggered_squat' => 65,
4150
'step_up' => 66,
4151
'weighted_step_up' => 67,
4152
'suitcase_squats' => 68,
4153
'sumo_squat' => 69,
4154
'sumo_squat_slide_in' => 70,
4155
'weighted_sumo_squat_slide_in' => 71,
4156
'sumo_squat_to_high_pull' => 72,
4157
'sumo_squat_to_stand' => 73,
4158
'weighted_sumo_squat_to_stand' => 74,
4159
'sumo_squat_with_rotation' => 75,
4160
'weighted_sumo_squat_with_rotation' => 76,
4161
'swiss_ball_body_weight_wall_squat' => 77,
4162
'weighted_swiss_ball_wall_squat' => 78,
4163
'thrusters' => 79,
4164
'uneven_squat' => 80,
4165
'weighted_uneven_squat' => 81,
4166
'waist_slimming_squat' => 82,
4167
'wall_ball' => 83,
4168
'wide_stance_barbell_squat' => 84,
4169
'wide_stance_goblet_squat' => 85,
4170
'zercher_squat' => 86,
4171
'kbs_overhead' => 87, # Deprecated do not use
4172
'squat_and_side_kick' => 88,
4173
'squat_jumps_in_n_out' => 89,
4174
'pilates_plie_squats_parallel_turned_out_flat_and_heels' => 90,
4175
'releve_straight_leg_and_knee_bent_with_one_leg_variation' => 91,
4176
},
4177
4178
'total_body_exercise_name' => +{
4179
'_base_type' => FIT_UINT16,
4180
'burpee' => 0,
4181
'weighted_burpee' => 1,
4182
'burpee_box_jump' => 2,
4183
'weighted_burpee_box_jump' => 3,
4184
'high_pull_burpee' => 4,
4185
'man_makers' => 5,
4186
'one_arm_burpee' => 6,
4187
'squat_thrusts' => 7,
4188
'weighted_squat_thrusts' => 8,
4189
'squat_plank_push_up' => 9,
4190
'weighted_squat_plank_push_up' => 10,
4191
'standing_t_rotation_balance' => 11,
4192
'weighted_standing_t_rotation_balance' => 12,
4193
},
4194
4195
'triceps_extension_exercise_name' => +{
4196
'_base_type' => FIT_UINT16,
4197
'bench_dip' => 0,
4198
'weighted_bench_dip' => 1,
4199
'body_weight_dip' => 2,
4200
'cable_kickback' => 3,
4201
'cable_lying_triceps_extension' => 4,
4202
'cable_overhead_triceps_extension' => 5,
4203
'dumbbell_kickback' => 6,
4204
'dumbbell_lying_triceps_extension' => 7,
4205
'ez_bar_overhead_triceps_extension' => 8,
4206
'incline_dip' => 9,
4207
'weighted_incline_dip' => 10,
4208
'incline_ez_bar_lying_triceps_extension' => 11,
4209
'lying_dumbbell_pullover_to_extension' => 12,
4210
'lying_ez_bar_triceps_extension' => 13,
4211
'lying_triceps_extension_to_close_grip_bench_press' => 14,
4212
'overhead_dumbbell_triceps_extension' => 15,
4213
'reclining_triceps_press' => 16,
4214
'reverse_grip_pressdown' => 17,
4215
'reverse_grip_triceps_pressdown' => 18,
4216
'rope_pressdown' => 19,
4217
'seated_barbell_overhead_triceps_extension' => 20,
4218
'seated_dumbbell_overhead_triceps_extension' => 21,
4219
'seated_ez_bar_overhead_triceps_extension' => 22,
4220
'seated_single_arm_overhead_dumbbell_extension' => 23,
4221
'single_arm_dumbbell_overhead_triceps_extension' => 24,
4222
'single_dumbbell_seated_overhead_triceps_extension' => 25,
4223
'single_leg_bench_dip_and_kick' => 26,
4224
'weighted_single_leg_bench_dip_and_kick' => 27,
4225
'single_leg_dip' => 28,
4226
'weighted_single_leg_dip' => 29,
4227
'static_lying_triceps_extension' => 30,
4228
'suspended_dip' => 31,
4229
'weighted_suspended_dip' => 32,
4230
'swiss_ball_dumbbell_lying_triceps_extension' => 33,
4231
'swiss_ball_ez_bar_lying_triceps_extension' => 34,
4232
'swiss_ball_ez_bar_overhead_triceps_extension' => 35,
4233
'tabletop_dip' => 36,
4234
'weighted_tabletop_dip' => 37,
4235
'triceps_extension_on_floor' => 38,
4236
'triceps_pressdown' => 39,
4237
'weighted_dip' => 40,
4238
},
4239
4240
'warm_up_exercise_name' => +{
4241
'_base_type' => FIT_UINT16,
4242
'quadruped_rocking' => 0,
4243
'neck_tilts' => 1,
4244
'ankle_circles' => 2,
4245
'ankle_dorsiflexion_with_band' => 3,
4246
'ankle_internal_rotation' => 4,
4247
'arm_circles' => 5,
4248
'bent_over_reach_to_sky' => 6,
4249
'cat_camel' => 7,
4250
'elbow_to_foot_lunge' => 8,
4251
'forward_and_backward_leg_swings' => 9,
4252
'groiners' => 10,
4253
'inverted_hamstring_stretch' => 11,
4254
'lateral_duck_under' => 12,
4255
'neck_rotations' => 13,
4256
'opposite_arm_and_leg_balance' => 14,
4257
'reach_roll_and_lift' => 15,
4258
'scorpion' => 16, # Deprecated do not use
4259
'shoulder_circles' => 17,
4260
'side_to_side_leg_swings' => 18,
4261
'sleeper_stretch' => 19,
4262
'slide_out' => 20,
4263
'swiss_ball_hip_crossover' => 21,
4264
'swiss_ball_reach_roll_and_lift' => 22,
4265
'swiss_ball_windshield_wipers' => 23,
4266
'thoracic_rotation' => 24,
4267
'walking_high_kicks' => 25,
4268
'walking_high_knees' => 26,
4269
'walking_knee_hugs' => 27,
4270
'walking_leg_cradles' => 28,
4271
'walkout' => 29,
4272
'walkout_from_push_up_position' => 30,
4273
},
4274
4275
'run_exercise_name' => +{
4276
'_base_type' => FIT_UINT16,
4277
'run' => 0,
4278
'walk' => 1,
4279
'jog' => 2,
4280
'sprint' => 3,
4281
},
4282
4283
'water_type' => +{
4284
'_base_type' => FIT_ENUM,
4285
'fresh' => 0,
4286
'salt' => 1,
4287
'en13319' => 2,
4288
'custom' => 3,
4289
},
4290
4291
'tissue_model_type' => +{
4292
'_base_type' => FIT_ENUM,
4293
'zhl_16c' => 0, # Buhlmann's decompression algorithm, version C
4294
},
4295
4296
'dive_gas_status' => +{
4297
'_base_type' => FIT_ENUM,
4298
'disabled' => 0,
4299
'enabled' => 1,
4300
'backup_only' => 2,
4301
},
4302
4303
'dive_alert' => +{
4304
'_base_type' => FIT_ENUM,
4305
'ndl_reached' => 0,
4306
'gas_switch_prompted' => 1,
4307
'near_surface' => 2,
4308
'approaching_ndl' => 3,
4309
'po2_warn' => 4,
4310
'po2_crit_high' => 5,
4311
'po2_crit_low' => 6,
4312
'time_alert' => 7,
4313
'depth_alert' => 8,
4314
'deco_ceiling_broken' => 9,
4315
'deco_complete' => 10,
4316
'safety_stop_broken' => 11,
4317
'safety_stop_complete' => 12,
4318
'cns_warning' => 13,
4319
'cns_critical' => 14,
4320
'otu_warning' => 15,
4321
'otu_critical' => 16,
4322
'ascent_critical' => 17,
4323
'alert_dismissed_by_key' => 18,
4324
'alert_dismissed_by_timeout' => 19,
4325
'battery_low' => 20,
4326
'battery_critical' => 21,
4327
'safety_stop_started' => 22,
4328
'approaching_first_deco_stop' => 23,
4329
'setpoint_switch_auto_low' => 24,
4330
'setpoint_switch_auto_high' => 25,
4331
'setpoint_switch_manual_low' => 26,
4332
'setpoint_switch_manual_high' => 27,
4333
'auto_setpoint_switch_ignored' => 28,
4334
'switched_to_open_circuit' => 29,
4335
'switched_to_closed_circuit' => 30,
4336
'tank_battery_low' => 32,
4337
'po2_ccr_dil_low' => 33, # ccr diluent has low po2
4338
'deco_stop_cleared' => 34, # a deco stop has been cleared
4339
'apnea_neutral_buoyancy' => 35, # Target Depth Apnea Alarm triggered
4340
'apnea_target_depth' => 36, # Neutral Buoyance Apnea Alarm triggered
4341
'apnea_surface' => 37, # Surface Apnea Alarm triggered
4342
'apnea_high_speed' => 38, # High Speed Apnea Alarm triggered
4343
'apnea_low_speed' => 39, # Low Speed Apnea Alarm triggered
4344
},
4345
4346
'dive_alarm_type' => +{
4347
'_base_type' => FIT_ENUM,
4348
'depth' => 0,
4349
'time' => 1,
4350
'speed' => 2, # Alarm when a certain ascent or descent rate is exceeded
4351
},
4352
4353
'dive_backlight_mode' => +{
4354
'_base_type' => FIT_ENUM,
4355
'at_depth' => 0,
4356
'always_on' => 1,
4357
},
4358
4359
'ccr_setpoint_switch_mode' => +{
4360
'_base_type' => FIT_ENUM,
4361
'manual' => 0, # User switches setpoints manually
4362
'automatic' => 1, # Switch automatically based on depth
4363
},
4364
4365
'dive_gas_mode' => +{
4366
'_base_type' => FIT_ENUM,
4367
'open_circuit' => 0,
4368
'closed_circuit_diluent' => 1,
4369
},
4370
4371
'favero_product' => +{
4372
'_base_type' => FIT_UINT16,
4373
'assioma_uno' => 10,
4374
'assioma_duo' => 12,
4375
},
4376
4377
'split_type' => +{
4378
'_base_type' => FIT_ENUM,
4379
'ascent_split' => 1,
4380
'descent_split' => 2,
4381
'interval_active' => 3,
4382
'interval_rest' => 4,
4383
'interval_warmup' => 5,
4384
'interval_cooldown' => 6,
4385
'interval_recovery' => 7,
4386
'interval_other' => 8,
4387
'climb_active' => 9,
4388
'climb_rest' => 10,
4389
'surf_active' => 11,
4390
'run_active' => 12,
4391
'run_rest' => 13,
4392
'workout_round' => 14,
4393
'rwd_run' => 17, # run/walk detection running
4394
'rwd_walk' => 18, # run/walk detection walking
4395
'windsurf_active' => 21,
4396
'rwd_stand' => 22, # run/walk detection standing
4397
'transition' => 23, # Marks the time going from ascent_split to descent_split/used in backcountry ski
4398
'ski_lift_split' => 28,
4399
'ski_run_split' => 29,
4400
},
4401
4402
'climb_pro_event' => +{
4403
'_base_type' => FIT_ENUM,
4404
'approach' => 0,
4405
'start' => 1,
4406
'complete' => 2,
4407
},
4408
4409
'gas_consumption_rate_type' => +{
4410
'_base_type' => FIT_ENUM,
4411
'pressure_sac' => 0, # Pressure-based Surface Air Consumption
4412
'volume_sac' => 1, # Volumetric Surface Air Consumption
4413
'rmv' => 2, # Respiratory Minute Volume
4414
},
4415
4416
'tap_sensitivity' => +{
4417
'_base_type' => FIT_ENUM,
4418
'high' => 0,
4419
'medium' => 1,
4420
'low' => 2,
4421
},
4422
4423
'radar_threat_level_type' => +{
4424
'_base_type' => FIT_ENUM,
4425
'threat_unknown' => 0,
4426
'threat_none' => 1,
4427
'threat_approaching' => 2,
4428
'threat_approaching_fast' => 3,
4429
},
4430
4431
'no_fly_time_mode' => +{
4432
'_base_type' => FIT_ENUM,
4433
'standard' => 0, # Standard Diver Alert Network no-fly guidance
4434
'flat_24_hours' => 1, # Flat 24 hour no-fly guidance
4435
},
4436
4437
);
4438
4439
for my $typenam (keys %named_type) { # if a type was _moved_to, copy the new href to $named_type{$typenam}
4440
my $typedesc = $named_type{$typenam};
4441
if (defined $typedesc->{_moved_to} and $typedesc->{_moved_to} ne '') {
4442
if ($typenam ne 'device_type') { $DB::single=1 } # want to know if it applies to others
4443
my $to = $named_type{$typedesc->{_moved_to}};
4444
$named_type{$typenam} = {%$to} if ref $to eq 'HASH'
4445
}
4446
}
4447
while (my ($typenam, $typedesc) = each %named_type) {
4448
# copy and flip key/value pairs of all hrefs in %named_type (except _base_type, _mask, …)
4449
for my $name (grep {!/^_/} keys %$typedesc) {
4450
$typedesc->{$typedesc->{$name}} = $name
4451
}
4452
}
4453
4454
my %msgtype_by_name = (
4455
'file_id' => +{ # begins === Common messages === section
4456
0 => +{'name' => 'type', 'type_name' => 'file'},
4457
1 => +{'name' => 'manufacturer', 'type_name' => 'manufacturer'},
4458
4459
2 => +{
4460
'name' => 'product',
4461
4462
'switch' => +{
4463
'_by' => 'manufacturer',
4464
'garmin' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
4465
'dynastream' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
4466
'dynastream_oem' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
4467
'favero_electronics' => +{'name' => 'favero_product', 'type_name' => 'favero_product'},
4468
'tacx' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
4469
},
4470
},
4471
4472
3 => +{'name' => 'serial_number'},
4473
4 => +{'name' => 'time_created', 'type_name' => 'date_time'},
4474
5 => +{'name' => 'number'},
4475
7 => +{'name' => 'unknown7'}, # unknown UINT32
4476
8 => +{'name' => 'product_name'},
4477
},
4478
4479
'file_creator' => +{
4480
0 => +{'name' => 'software_version'},
4481
1 => +{'name' => 'hardware_version'},
4482
},
4483
4484
'timestamp_correlation' => +{
4485
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
4486
0 => +{'name' => 'fractional_timestamp', 'scale' => 32768, 'unit' => 's'},
4487
1 => +{'name' => 'system_timestamp', 'type_name' => 'date_time'},
4488
2 => +{'name' => 'fractional_system_timestamp', 'scale' => 32768, 'unit' => 's'},
4489
3 => +{'name' => 'local_timestamp', 'type_name' => 'local_date_time'},
4490
4 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
4491
5 => +{'name' => 'system_timestamp_ms', 'unit' => 'ms'},
4492
},
4493
4494
'software' => +{ # begins === Device file messages === section
4495
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4496
3 => +{'name' => 'version', 'scale' => 100},
4497
5 => +{'name' => 'part_number'},
4498
},
4499
4500
'slave_device' => +{
4501
0 => +{'name' => 'manufacturer', 'type_name' => 'manufacturer'},
4502
4503
1 => +{
4504
'name' => 'product',
4505
4506
'switch' => +{
4507
'_by' => 'manufacturer',
4508
'garmin' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
4509
'dynastream' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
4510
'dynastream_oem' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
4511
'favero_electronics' => +{'name' => 'favero_product', 'type_name' => 'favero_product'},
4512
'tacx' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
4513
},
4514
},
4515
},
4516
4517
'capabilities' => +{
4518
0 => +{'name' => 'languages'},
4519
1 => +{'name' => 'sports', 'type_name' => 'sport_bits_0'},
4520
21 => +{'name' => 'workouts_supported', 'type_name' => 'workout_capabilities'},
4521
22 => +{'name' => 'unknown22'}, # unknown ENUM
4522
23 => +{'name' => 'connectivity_supported', 'type_name' => 'connectivity_capabilities'},
4523
24 => +{'name' => 'unknown24'}, # unknown ENUM
4524
25 => +{'name' => 'unknown25'}, # unknown UINT32Z
4525
},
4526
4527
'file_capabilities' => +{
4528
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4529
0 => +{'name' => 'type', 'type_name' => 'file'},
4530
1 => +{'name' => 'flags', 'type_name' => 'file_flags'},
4531
2 => +{'name' => 'directory'},
4532
3 => +{'name' => 'max_count'},
4533
4 => +{'name' => 'max_size', 'unit' => 'bytes'},
4534
},
4535
4536
'mesg_capabilities' => +{
4537
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4538
0 => +{'name' => 'file', 'type_name' => 'file'},
4539
1 => +{'name' => 'mesg_num', 'type_name' => 'mesg_num'},
4540
2 => +{'name' => 'count_type', 'type_name' => 'mesg_count'},
4541
4542
3 => +{
4543
'name' => 'count',
4544
4545
'switch' => +{
4546
'_by' => 'count_type',
4547
'num_per_file' => +{'name' => 'num_per_file'},
4548
'max_per_file' => +{'name' => 'max_per_file'},
4549
'max_per_file_type' => +{'name' => 'max_per_file_type'},
4550
},
4551
},
4552
},
4553
4554
'field_capabilities' => +{
4555
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4556
0 => +{'name' => 'file', 'type_name' => 'file'},
4557
1 => +{'name' => 'mesg_num', 'type_name' => 'mesg_num'},
4558
2 => +{'name' => 'field_num'},
4559
3 => +{'name' => 'count'},
4560
4 => +{'name' => 'bits'}, # not present? PATJOL: I don't see this one in the profile
4561
},
4562
4563
'device_settings' => +{ # begins === Settings file messages === section
4564
0 => +{'name' => 'active_time_zone'},
4565
1 => +{'name' => 'utc_offset'},
4566
2 => +{'name' => 'time_offset', 'unit' => 's'},
4567
3 => +{'name' => 'unknown3'}, # unknown ENUM
4568
4 => +{'name' => 'time_mode', 'type_name' => 'time_mode'},
4569
5 => +{'name' => 'time_zone_offset', 'scale' => 4, 'unit' => 'hr'},
4570
10 => +{'name' => 'unknown10'}, # unknown ENUM
4571
11 => +{'name' => 'unknown11'}, # unknown ENUM
4572
12 => +{'name' => 'backlight_mode', 'type_name' => 'backlight_mode'},
4573
13 => +{'name' => 'unknown13'}, # unknown UINT8
4574
14 => +{'name' => 'unknown14'}, # unknown UINT8
4575
15 => +{'name' => 'unknown15'}, # unknown UINT8
4576
16 => +{'name' => 'unknown16'}, # unknown ENUM
4577
17 => +{'name' => 'unknown17'}, # unknown ENUM
4578
18 => +{'name' => 'unknown18'}, # unknown ENUM
4579
21 => +{'name' => 'unknown21'}, # unknown ENUM
4580
22 => +{'name' => 'unknown22'}, # unknown ENUM
4581
26 => +{'name' => 'unknown26'}, # unknown ENUM
4582
27 => +{'name' => 'unknown27'}, # unknown ENUM
4583
29 => +{'name' => 'unknown29'}, # unknown ENUM
4584
33 => +{'name' => 'unknown33'}, # unknown UNIT8
4585
36 => +{'name' => 'activity_tracker_enabled', 'type_name' => 'bool'},
4586
38 => +{'name' => 'unknown38'}, # unknown ENUM
4587
39 => +{'name' => 'clock_time', 'type_name' => 'date_time'},
4588
40 => +{'name' => 'pages_enabled'},
4589
41 => +{'name' => 'unknown41'}, # unknown ENUM
4590
46 => +{'name' => 'move_alert_enabled', 'type_name' => 'bool'},
4591
47 => +{'name' => 'date_mode', 'type_name' => 'date_mode'},
4592
48 => +{'name' => 'unknown48'}, # unknown ENUM
4593
49 => +{'name' => 'unknown49'}, # unknown UINT16
4594
52 => +{'name' => 'unknown52'}, # unknown ENUM
4595
53 => +{'name' => 'unknown53'}, # unknown ENUM
4596
54 => +{'name' => 'unknown54'}, # unknown ENUM
4597
55 => +{'name' => 'display_orientation', 'type_name' => 'display_orientation'},
4598
56 => +{'name' => 'mounting_side', 'type_name' => 'side'},
4599
57 => +{'name' => 'default_page'},
4600
58 => +{'name' => 'autosync_min_steps', 'unit' => 'steps'},
4601
59 => +{'name' => 'autosync_min_time', 'unit' => 'minutes'},
4602
75 => +{'name' => 'unknown75'}, # unknown ENUM
4603
80 => +{'name' => 'lactate_threshold_autodetect_enabled', 'type_name' => 'bool'},
4604
85 => +{'name' => 'unknown85'}, # unknown ENUM
4605
86 => +{'name' => 'ble_auto_upload_enabled', 'type_name' => 'bool'},
4606
89 => +{'name' => 'auto_sync_frequency', 'type_name' => 'auto_sync_frequency'},
4607
90 => +{'name' => 'auto_activity_detect', 'type_name' => 'auto_activity_detect'},
4608
94 => +{'name' => 'number_of_screens'},
4609
95 => +{'name' => 'smart_notification_display_orientation', 'type_name' => 'display_orientation'},
4610
97 => +{'name' => 'unknown97'}, # unknown UINT8Z
4611
98 => +{'name' => 'unknown98'}, # unknown ENUM
4612
103 => +{'name' => 'unknown103'}, # unknown ENUM
4613
134 => +{'name' => 'tap_interface', 'type_name' => 'switch'},
4614
174 => +{'name' => 'tap_sensitivity', 'type_name' => 'tap_sensitivity'},
4615
},
4616
4617
'user_profile' => +{
4618
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4619
0 => +{'name' => 'friendly_name'},
4620
1 => +{'name' => 'gender', 'type_name' => 'gender'},
4621
2 => +{'name' => 'age', 'unit' => 'years'},
4622
3 => +{'name' => 'height', scale => 100, 'unit' => 'm'},
4623
4 => +{'name' => 'weight', scale => 10, 'unit' => 'kg'},
4624
5 => +{'name' => 'language', 'type_name' => 'language'},
4625
6 => +{'name' => 'elev_setting', 'type_name' => 'display_measure'},
4626
7 => +{'name' => 'weight_setting', 'type_name' => 'display_measure'},
4627
8 => +{'name' => 'resting_heart_rate', 'unit' => 'bpm'},
4628
9 => +{'name' => 'default_max_running_heart_rate', 'unit' => 'bpm'},
4629
10 => +{'name' => 'default_max_biking_heart_rate', 'unit' => 'bpm'},
4630
11 => +{'name' => 'default_max_heart_rate', 'unit' => 'bpm'},
4631
12 => +{'name' => 'hr_setting', 'type_name' => 'display_heart'},
4632
13 => +{'name' => 'speed_setting', 'type_name' => 'display_measure'},
4633
14 => +{'name' => 'dist_setting', 'type_name' => 'display_measure'},
4634
16 => +{'name' => 'power_setting', 'type_name' => 'display_power'},
4635
17 => +{'name' => 'activity_class', 'type_name' => 'activity_class'},
4636
18 => +{'name' => 'position_setting', 'type_name' => 'display_position'},
4637
21 => +{'name' => 'temperature_setting', 'type_name' => 'display_measure'},
4638
22 => +{'name' => 'local_id', 'type_name' => 'user_local_id'},
4639
23 => +{'name' => 'global_id'},
4640
24 => +{'name' => 'unknown24'}, # unknown UINT8
4641
28 => +{'name' => 'wake_time', 'type_name' => 'localtime_into_day'},
4642
29 => +{'name' => 'sleep_time', 'type_name' => 'localtime_into_day'},
4643
30 => +{'name' => 'height_setting', 'type_name' => 'display_measure'},
4644
31 => +{'name' => 'user_running_step_length', scale => 1000, 'unit' => 'm'},
4645
32 => +{'name' => 'user_walking_step_length', scale => 1000, 'unit' => 'm'},
4646
33 => +{'name' => 'unknown33'}, # unknown UINT16
4647
34 => +{'name' => 'unknown34'}, # unknown UINT16
4648
35 => +{'name' => 'unknown35'}, # unknown UINT32
4649
36 => +{'name' => 'unknown36'}, # unknown UINT8
4650
38 => +{'name' => 'unknown38'}, # unknown UINT16
4651
40 => +{'name' => 'unknown40'}, # unknown FLOAT32
4652
42 => +{'name' => 'unknown42'}, # unknown UINT32
4653
47 => +{'name' => 'depth_setting', 'type_name' => 'display_measure'},
4654
49 => +{'name' => 'dive_count'},
4655
},
4656
4657
'hrm_profile' => +{
4658
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4659
0 => +{'name' => 'enabled', 'type_name' => 'bool'},
4660
1 => +{'name' => 'hrm_ant_id'},
4661
2 => +{'name' => 'log_hrv', 'type_name' => 'bool'},
4662
3 => +{'name' => 'hrm_ant_id_trans_type'},
4663
},
4664
4665
'sdm_profile' => +{
4666
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4667
0 => +{'name' => 'enabled', 'type_name' => 'bool'},
4668
1 => +{'name' => 'sdm_ant_id'},
4669
2 => +{'name' => 'sdm_cal_factor', 'scale' => 10, 'unit' => '%'},
4670
3 => +{'name' => 'odometer', 'scale' => 100, 'unit' => 'm'},
4671
4 => +{'name' => 'speed_source', 'type_name' => 'bool'},
4672
5 => +{'name' => 'sdm_ant_id_trans_type'},
4673
7 => +{'name' => 'odometer_rollover'},
4674
},
4675
4676
'bike_profile' => +{
4677
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4678
0 => +{'name' => 'name'},
4679
1 => +{'name' => 'sport', 'type_name' => 'sport'},
4680
2 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
4681
3 => +{'name' => 'odometer', 'scale' => 100, 'unit' => 'm'},
4682
4 => +{'name' => 'bike_spd_ant_id'},
4683
5 => +{'name' => 'bike_cad_ant_id'},
4684
6 => +{'name' => 'bike_spdcad_ant_id'},
4685
7 => +{'name' => 'bike_power_ant_id'},
4686
8 => +{'name' => 'custom_wheelsize', 'scale' => 1000, 'unit' => 'm'},
4687
9 => +{'name' => 'auto_wheelsize', 'scale' => 1000, 'unit' => 'm'},
4688
10 => +{'name' => 'bike_weight', 'scale' => 10, 'unit' => 'kg'},
4689
11 => +{'name' => 'power_cal_factor', 'scale' => 10, 'unit' => '%'},
4690
12 => +{'name' => 'auto_wheel_cal', 'type_name' => 'bool'},
4691
13 => +{'name' => 'auto_power_zero', 'type_name' => 'bool'},
4692
14 => +{'name' => 'id'},
4693
15 => +{'name' => 'spd_enabled', 'type_name' => 'bool'},
4694
16 => +{'name' => 'cad_enabled', 'type_name' => 'bool'},
4695
17 => +{'name' => 'spdcad_enabled', 'type_name' => 'bool'},
4696
18 => +{'name' => 'power_enabled', 'type_name' => 'bool'},
4697
19 => +{'name' => 'crank_length', 'scale' => 2, 'offset' => -110, 'unit' => 'mm'},
4698
20 => +{'name' => 'enabled', 'type_name' => 'bool'},
4699
21 => +{'name' => 'bike_spd_ant_id_trans_type'},
4700
22 => +{'name' => 'bike_cad_ant_id_trans_type'},
4701
23 => +{'name' => 'bike_spdcad_ant_id_trans_type'},
4702
24 => +{'name' => 'bike_power_ant_id_trans_type'},
4703
35 => +{'name' => 'unknown35'}, # unknown UINT8 (array[3])
4704
36 => +{'name' => 'unknown36'}, # unknown ENUM
4705
37 => +{'name' => 'odometer_rollover'},
4706
38 => +{'name' => 'front_gear_num'},
4707
39 => +{'name' => 'front_gear'},
4708
40 => +{'name' => 'rear_gear_num'},
4709
41 => +{'name' => 'rear_gear'},
4710
44 => +{'name' => 'shimano_di2_enabled'},
4711
},
4712
4713
'connectivity' => +{
4714
0 => +{'name' => 'bluetooth_enabled', 'type_name' => 'bool'},
4715
1 => +{'name' => 'bluetooth_le_enabled', 'type_name' => 'bool'},
4716
2 => +{'name' => 'ant_enabled', 'type_name' => 'bool'},
4717
3 => +{'name' => 'name'},
4718
4 => +{'name' => 'live_tracking_enabled', 'type_name' => 'bool'},
4719
5 => +{'name' => 'weather_conditions_enabled', 'type_name' => 'bool'},
4720
6 => +{'name' => 'weather_alerts_enabled', 'type_name' => 'bool'},
4721
7 => +{'name' => 'auto_activity_upload_enabled', 'type_name' => 'bool'},
4722
8 => +{'name' => 'course_download_enabled', 'type_name' => 'bool'},
4723
9 => +{'name' => 'workout_download_enabled', 'type_name' => 'bool'},
4724
10 => +{'name' => 'gps_ephemeris_download_enabled', 'type_name' => 'bool'},
4725
11 => +{'name' => 'incident_detection_enabled', 'type_name' => 'bool'},
4726
12 => +{'name' => 'grouptrack_enabled', 'type_name' => 'bool'},
4727
},
4728
4729
'watchface_settings' => +{
4730
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4731
0 => +{'name' => 'mode', 'type_name' => 'watchface_mode'},
4732
4733
1 => +{
4734
'name' => 'layout',
4735
4736
'switch' => +{
4737
'_by' => 'mode',
4738
'digital' => +{'name' => 'digital_layout', 'type_name' => 'digital_watchface_layout'},
4739
'analog' => +{'name' => 'analog_layout', 'type_name' => 'analog_watchface_layout'},
4740
},
4741
},
4742
},
4743
4744
'ohr_settings' => +{
4745
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
4746
0 => +{'name' => 'enabled', 'type_name' => 'switch'},
4747
},
4748
4749
'time_in_zone' => +{
4750
253 => +{ 'name' => 'timestamp', 'type_name' => 'date_time' },
4751
0 => +{ 'name' => 'reference_mesg', 'type_name' => 'mesg_num' },
4752
1 => +{ 'name' => 'reference_index', 'type_name' => 'message_index' },
4753
2 => +{ 'name' => 'time_in_hr_zone', 'scale' => 1000 },
4754
3 => +{ 'name' => 'time_in_speed_zone', 'scale' => 1000 },
4755
4 => +{ 'name' => 'time_in_cadence_zone', 'scale' => 1000 },
4756
5 => +{ 'name' => 'time_in_power_zone', 'scale' => 1000 },
4757
6 => +{ 'name' => 'hr_zone_high_boundary', 'unit' => 'bpm' },
4758
7 => +{ 'name' => 'speed_zone_high_boundary', 'unit' => 'm/s', 'scale' => 1000 },
4759
8 => +{ 'name' => 'cadence_zone_high_boundary', 'unit' => 'rpm' },
4760
9 => +{ 'name' => 'power_zone_high_boundary', 'unit' => 'watts' },
4761
10 => +{ 'name' => 'hr_calc_type', 'type_name' => 'hr_zone_calc' },
4762
11 => +{ 'name' => 'max_heart_rate' },
4763
12 => +{ 'name' => 'resting_heart_rate' },
4764
13 => +{ 'name' => 'threshold_heart_rate' },
4765
14 => +{ 'name' => 'pwr_calc_type', 'type_name' => 'pwr_zone_calc' },
4766
15 => +{ 'name' => 'functional_threshold_power' },
4767
},
4768
4769
'zones_target' => +{ # begins === Sport settings file messages === section
4770
1 => +{'name' => 'max_heart_rate', 'unit' => 'bpm'},
4771
2 => +{'name' => 'threshold_heart_rate', 'unit' => 'bpm'},
4772
3 => +{'name' => 'functional_threshold_power', 'unit' => 'watts'},
4773
5 => +{'name' => 'hr_calc_type', 'type_name' => 'hr_zone_calc'},
4774
7 => +{'name' => 'pwr_calc_type', 'type_name' => 'power_zone_calc'},
4775
8 => +{'name' => 'unknown8'}, # unknown UINT16
4776
9 => +{'name' => 'unknown9'}, # unknown ENUM
4777
10 => +{'name' => 'unknown10'}, # unknown ENUM
4778
11 => +{'name' => 'unknown11'}, # unknown ENUM
4779
12 => +{'name' => 'unknown12'}, # unknown ENUM
4780
13 => +{'name' => 'unknown13'}, # unknown ENUM
4781
},
4782
4783
'sport' => +{
4784
0 => +{'name' => 'sport', 'type_name' => 'sport'},
4785
1 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
4786
3 => +{'name' => 'name'},
4787
4 => +{'name' => 'unknown4'}, # unknown UINT16
4788
5 => +{'name' => 'unknown5'}, # unknown ENUM
4789
6 => +{'name' => 'unknown6'}, # unknown ENUM
4790
7 => +{'name' => 'unknown7'}, # unknown UINT8
4791
8 => +{'name' => 'unknown8'}, # unknown UINT8
4792
9 => +{'name' => 'unknown9'}, # unknown UINT8
4793
10 => +{'name' => 'unknown10'}, # unknown UINT8 (array[3])
4794
12 => +{'name' => 'unknown12'}, # unknown UINT8
4795
},
4796
4797
'hr_zone' => +{
4798
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4799
1 => +{'name' => 'high_bpm', 'unit' => 'bpm'},
4800
2 => +{'name' => 'name'},
4801
},
4802
4803
'speed_zone' => +{
4804
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4805
0 => +{'name' => 'high_value', 'scale' => 1000, 'unit' => 'm/s'},
4806
1 => +{'name' => 'name'},
4807
},
4808
4809
'cadence_zone' => +{
4810
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4811
0 => +{'name' => 'high_value', 'unit' => 'rpm'},
4812
1 => +{'name' => 'name'},
4813
},
4814
4815
'power_zone' => +{
4816
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4817
1 => +{'name' => 'high_value', 'unit' => 'watts'},
4818
2 => +{'name' => 'name'},
4819
},
4820
4821
'met_zone' => +{
4822
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4823
1 => +{'name' => 'high_bpm', 'unit' => 'bpm'},
4824
2 => +{'name' => 'calories', 'scale' => 10, 'unit' => 'kcal/min'},
4825
3 => +{'name' => 'fat_calories', 'scale' => 10, 'unit' => 'kcal/min'},
4826
},
4827
4828
'dive_settings' => +{
4829
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
4830
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4831
0 => +{'name' => 'name'},
4832
1 => +{'name' => 'model', 'type_name' => 'tissue_model_type'},
4833
2 => +{'name' => 'gf_low', 'unit' => '%'},
4834
3 => +{'name' => 'gf_high', 'unit' => '%'},
4835
4 => +{'name' => 'water_type', 'type_name' => 'water_type'},
4836
5 => +{'name' => 'water_density', 'unit' => 'kg/m^3'},
4837
6 => +{'name' => 'po2_warn', 'scale' => 100, 'unit' => '%'},
4838
7 => +{'name' => 'po2_critical', 'scale' => 100, 'unit' => '%'},
4839
8 => +{'name' => 'po2_deco', 'scale' => 100, 'unit' => '%'},
4840
9 => +{'name' => 'safety_stop_enabled', 'type_name' => 'bool'},
4841
10 => +{'name' => 'bottom_depth'},
4842
11 => +{'name' => 'bottom_time'},
4843
12 => +{'name' => 'apnea_countdown_enabled', 'type_name' => 'bool'},
4844
13 => +{'name' => 'apnea_countdown_time'},
4845
14 => +{'name' => 'backlight_mode', 'type_name' => 'dive_backlight_mode'},
4846
15 => +{'name' => 'backlight_brightness'},
4847
16 => +{'name' => 'backlight_timeout', 'type_name' => 'backlight_timeout'},
4848
17 => +{'name' => 'repeat_dive_interval', 'unit' => 's'},
4849
18 => +{'name' => 'safety_stop_time', 'unit' => 's'},
4850
19 => +{'name' => 'heart_rate_source_type', 'type_name' => 'source_type'},
4851
20 => +{
4852
'name' => 'heart_rate_source',
4853
'switch' => +{
4854
'_by' => 'heart_rate_source_type',
4855
'antplus' => +{'name' => 'heart_rate_antplus_device_type', 'type_name' => 'antplus_device_type'},
4856
'local' => +{'name' => 'heart_rate_local_device_type', 'type_name' => 'local_device_type'},
4857
},
4858
},
4859
21 => +{ 'name' => 'travel_gas', 'type_name' => 'message_index' }, # Index of travel dive_gas message
4860
22 => +{ 'name' => 'ccr_low_setpoint_switch_mode', 'type_name' => 'ccr_setpoint_switch_mode' }, # If low PO2 should be switched to automatically
4861
23 => +{ 'name' => 'ccr_low_setpoint', 'scale' => 100 }, # Target PO2 when using low setpoint
4862
24 => +{ 'name' => 'ccr_low_setpoint_depth', 'unit' => 'm', 'scale' => 1000 }, # Depth to switch to low setpoint in automatic mode
4863
25 => +{ 'name' => 'ccr_high_setpoint_switch_mode', 'type' => 'ccr_setpoint_switch_mode' }, # If high PO2 should be switched to automatically
4864
26 => +{ 'name' => 'ccr_high_setpoint', 'unit' => '%', 'scale' => 100 }, # Target PO2 when using high setpoint
4865
27 => +{ 'name' => 'ccr_high_setpoint_depth', 'unit' => 'm', 'scale' => 1000 }, # Depth to switch to high setpoint in automatic mode
4866
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.
4867
30 => +{ 'name' => 'up_key_enabled', 'type_name' => 'bool' }, # Indicates whether the up key is enabled during dives
4868
35 => +{ 'name' => 'dive_sounds', 'type_name' => 'tone' }, # Sounds and vibration enabled or disabled in-dive
4869
36 => +{ 'name' => 'last_stop_multiple', 'scale' => 10 }, # Usually 1.0/1.5/2.0 representing 3/4.5/6m or 10/15/20ft
4870
37 => +{ 'name' => 'no_fly_time_mode', 'type_name' => 'no_fly_time_mode' }, # Indicates which guidelines to use for no-fly surface interval.
4871
},
4872
4873
'dive_alarm' => +{
4874
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4875
0 => +{'name' => 'depth', 'scale' => 1000, 'unit' => 'm'},
4876
1 => +{'name' => 'time', 'unit' => 's'},
4877
2 => +{'name' => 'enabled', 'type_name' => 'bool'},
4878
3 => +{'name' => 'alarm_type', 'type_name' => 'dive_alarm_type'},
4879
4 => +{'name' => 'sound', 'type_name' => 'tone'},
4880
5 => +{'name' => 'dive_types', 'type_name' => 'sub_sport'},
4881
6 => +{ 'name' => 'id' }, # Alarm ID
4882
7 => +{ 'name' => 'popup_enabled', 'type_name' => 'bool' }, # Show a visible pop-up for this alarm
4883
8 => +{ 'name' => 'trigger_on_descent', 'type_name' => 'bool' }, # Trigger the alarm on descent
4884
9 => +{ 'name' => 'trigger_on_ascent', 'type_name' => 'bool' }, # Trigger the alarm on ascent
4885
10 => +{ 'name' => 'repeating', 'type_name' => 'bool' }, # Repeat alarm each time threshold is crossed?
4886
11 => +{ 'name' => 'speed', 'scale' => 1000 }, # Ascent/descent rate (mps) setting for speed type alarms
4887
},
4888
4889
'dive_apnea_alarm' => +{
4890
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4891
0 => +{ 'name' => 'depth', 'unit' => 'm', 'scale' => 1000 }, # Depth setting (m) for depth type alarms
4892
1 => +{ 'name' => 'time', 'unit' => 's' }, # Time setting (s) for time type alarms
4893
2 => +{ 'name' => 'enabled', 'type_name' => 'bool' }, # Enablement flag
4894
3 => +{ 'name' => 'alarm_type', 'type_name' => 'dive_alarm_type' }, # Alarm type setting
4895
4 => +{ 'name' => 'sound', 'type_name' => 'tone' }, # Tone and Vibe setting for the alarm.
4896
5 => +{ 'name' => 'dive_types', 'type_name' => 'sub_sport' }, # Dive types the alarm will trigger on
4897
6 => +{ 'name' => 'id' }, # Alarm ID
4898
7 => +{ 'name' => 'popup_enabled', 'type_name' => 'bool' }, # Show a visible pop-up for this alarm
4899
8 => +{ 'name' => 'trigger_on_descent', 'type_name' => 'bool' }, # Trigger the alarm on descent
4900
9 => +{ 'name' => 'trigger_on_ascent', 'type_name' => 'bool' }, # Trigger the alarm on ascent
4901
10 => +{ 'name' => 'repeating', 'type_name' => 'bool' }, # Repeat alarm each time threshold is crossed?
4902
11 => +{ 'name' => 'speed', 'unit' => 'mps', 'scale' => 1000 }, # Ascent/descent rate (mps) setting for speed type alarms
4903
},
4904
4905
'dive_gas' => +{
4906
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4907
0 => +{'name' => 'helium_content', 'unit' => '%'},
4908
1 => +{'name' => 'oxygen_content', 'unit' => '%'},
4909
2 => +{'name' => 'status', 'type_name' => 'dive_gas_status'},
4910
3 => +{'name' => 'mode', 'type_name' => 'dive_gas_mode'},
4911
},
4912
4913
'goal' => +{ # begins === Goals file messages === section
4914
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4915
0 => +{'name' => 'sport', 'type_name' => 'sport'},
4916
1 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
4917
2 => +{'name' => 'start_date', 'type_name' => 'date_time'},
4918
3 => +{'name' => 'end_date', 'type_name' => 'date_time'},
4919
4 => +{'name' => 'type', 'type_name' => 'goal'},
4920
5 => +{'name' => 'value'},
4921
6 => +{'name' => 'repeat', 'type_name' => 'bool'},
4922
7 => +{'name' => 'target_value'},
4923
8 => +{'name' => 'recurrence', 'type_name' => 'goal_recurrence'},
4924
9 => +{'name' => 'recurrence_value'},
4925
10 => +{'name' => 'enabled', 'type_name' => 'bool'},
4926
11 => +{'name' => 'source', 'type_name' => 'goal_source'},
4927
},
4928
4929
'activity' => +{ # begins === Activity file messages === section
4930
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
4931
0 => +{'name' => 'total_timer_time', 'scale' => 1000, 'unit' => 's'},
4932
1 => +{'name' => 'num_sessions'},
4933
2 => +{'name' => 'type', 'type_name' => 'activity'},
4934
3 => +{'name' => 'event', 'type_name' => 'event'},
4935
4 => +{'name' => 'event_type', 'type_name' => 'event_type'},
4936
5 => +{'name' => 'local_timestamp', 'type_name' => 'local_date_time'},
4937
6 => +{'name' => 'event_group'},
4938
},
4939
4940
'session' => +{
4941
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
4942
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
4943
0 => +{'name' => 'event', 'type_name' => 'event'},
4944
1 => +{'name' => 'event_type', 'type_name' => 'event_type'},
4945
2 => +{'name' => 'start_time', 'type_name' => 'date_time'},
4946
3 => +{'name' => 'start_position_lat', 'unit' => 'semicircles'},
4947
4 => +{'name' => 'start_position_long', 'unit' => 'semicircles'},
4948
5 => +{'name' => 'sport', 'type_name' => 'sport'},
4949
6 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
4950
7 => +{'name' => 'total_elapsed_time', 'scale' => 1000, 'unit' => 's'},
4951
8 => +{'name' => 'total_timer_time', 'scale' => 1000, 'unit' => 's'},
4952
9 => +{'name' => 'total_distance', 'scale' => 100, 'unit' => 'm'},
4953
4954
10 => +{
4955
'name' => 'total_cycles', 'unit' => 'cycles',
4956
4957
'switch' => +{
4958
'_by' => 'sport',
4959
'walking' => +{'name' => 'total_steps', 'unit' => 'steps'},
4960
'running' => +{'name' => 'total_strides', 'unit' => 'strides'},
4961
'swimming' => +{'name' => 'total_strokes', 'unit' => 'strokes'},
4962
},
4963
},
4964
4965
11 => +{'name' => 'total_calories', 'unit' => 'kcal'},
4966
13 => +{'name' => 'total_fat_calories', 'unit' => 'kcal'},
4967
14 => +{'name' => 'avg_speed', 'scale' => 1000, 'unit' => 'm/s'},
4968
15 => +{'name' => 'max_speed', 'scale' => 1000, 'unit' => 'm/s'},
4969
16 => +{'name' => 'avg_heart_rate', 'unit' => 'bpm'},
4970
17 => +{'name' => 'max_heart_rate', 'unit' => 'bpm'},
4971
4972
18 => +{
4973
'name' => 'avg_cadence', 'unit' => 'rpm',
4974
4975
'switch' => +{
4976
'_by' => 'sport',
4977
'walking' => +{'name' => 'avg_walking_cadence', 'unit' => 'steps/min'},
4978
'running' => +{'name' => 'avg_running_cadence', 'unit' => 'strides/min'},
4979
'swimming' => +{'name' => 'avg_swimming_cadence', 'unit' => 'strokes/min'},
4980
},
4981
},
4982
4983
19 => +{
4984
'name' => 'max_cadence', 'unit' => 'rpm',
4985
4986
'switch' => +{
4987
'_by' => 'sport',
4988
'walking' => +{'name' => 'max_walking_cadence', 'unit' => 'steps/min'},
4989
'running' => +{'name' => 'max_running_cadence', 'unit' => 'strides/min'},
4990
'swimming' => +{'name' => 'max_swimming_cadence', 'unit' => 'strokes/min'},
4991
},
4992
},
4993
4994
20 => +{'name' => 'avg_power', 'unit' => 'watts'},
4995
21 => +{'name' => 'max_power', 'unit' => 'watts'},
4996
22 => +{'name' => 'total_ascent', 'unit' => 'm'},
4997
23 => +{'name' => 'total_descent', 'unit' => 'm'},
4998
24 => +{'name' => 'total_training_effect', 'scale' => 10},
4999
25 => +{'name' => 'first_lap_index'},
5000
26 => +{'name' => 'num_laps'},
5001
27 => +{'name' => 'event_group'},
5002
28 => +{'name' => 'trigger', 'type_name' => 'session_trigger'},
5003
29 => +{'name' => 'nec_lat', 'unit' => 'semicircles'},
5004
30 => +{'name' => 'nec_long', 'unit' => 'semicircles'},
5005
31 => +{'name' => 'swc_lat', 'unit' => 'semicircles'},
5006
32 => +{'name' => 'swc_long', 'unit' => 'semicircles'},
5007
34 => +{'name' => 'normalized_power', 'unit' => 'watts'},
5008
35 => +{'name' => 'training_stress_score', 'scale' => 10, 'unit' => 'tss'},
5009
36 => +{'name' => 'intensity_factor', 'scale' => 1000, 'unit' => 'if'},
5010
37 => +{'name' => 'left_right_balance', 'type_name' => 'left_right_balance_100'},
5011
41 => +{'name' => 'avg_stroke_count', 'scale' => 10, 'unit' => 'strokes/lap'},
5012
42 => +{'name' => 'avg_stroke_distance', 'scale' => 100, 'unit' => 'm'},
5013
43 => +{'name' => 'swim_stroke', 'type_name' => 'swim_stroke'},
5014
44 => +{'name' => 'pool_length', 'scale' => 100, 'unit' => 'm'},
5015
45 => +{'name' => 'threshold_power', 'unit' => 'watts'},
5016
46 => +{'name' => 'pool_length_unit', 'type_name' => 'display_measure'},
5017
47 => +{'name' => 'num_active_lengths', 'unit' => 'lengths'},
5018
48 => +{'name' => 'total_work', 'unit' => 'J'},
5019
49 => +{'name' => 'avg_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5020
50 => +{'name' => 'max_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5021
51 => +{'name' => 'gps_accuracy', 'unit' => 'm'},
5022
52 => +{'name' => 'avg_grade', 'scale' => 100, 'unit' => '%'},
5023
53 => +{'name' => 'avg_pos_grade', 'scale' => 100, 'unit' => '%'},
5024
54 => +{'name' => 'avg_neg_grade', 'scale' => 100, 'unit' => '%'},
5025
55 => +{'name' => 'max_pos_grade', 'scale' => 100, 'unit' => '%'},
5026
56 => +{'name' => 'max_neg_grade', 'scale' => 100, 'unit' => '%'},
5027
57 => +{'name' => 'avg_temperature', 'unit' => 'deg.C'},
5028
58 => +{'name' => 'max_temperature', 'unit' => 'deg.C'},
5029
59 => +{'name' => 'total_moving_time', 'scale' => 1000, 'unit' => 's'},
5030
60 => +{'name' => 'avg_pos_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5031
61 => +{'name' => 'avg_neg_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5032
62 => +{'name' => 'max_pos_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5033
63 => +{'name' => 'max_neg_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5034
64 => +{'name' => 'min_heart_rate', 'unit' => 'bpm'},
5035
65 => +{'name' => 'time_in_hr_zone', 'scale' => 1000, 'unit' => 's'},
5036
66 => +{'name' => 'time_in_speed_zone', 'scale' => 1000, 'unit' => 's'},
5037
67 => +{'name' => 'time_in_cadence_zone', 'scale' => 1000, 'unit' => 's'},
5038
68 => +{'name' => 'time_in_power_zone', 'scale' => 1000, 'unit' => 's'},
5039
69 => +{'name' => 'avg_lap_time', 'scale' => 1000, 'unit' => 's'},
5040
70 => +{'name' => 'best_lap_index'},
5041
71 => +{'name' => 'min_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5042
78 => +{'name' => 'unknown78'}, # unknown UINT32
5043
81 => +{'name' => 'unknown81'}, # unknown ENUM
5044
82 => +{'name' => 'player_score'},
5045
83 => +{'name' => 'opponent_score'},
5046
84 => +{'name' => 'opponent_name'},
5047
85 => +{'name' => 'stroke_count', 'unit' => 'counts'},
5048
86 => +{'name' => 'zone_count', 'unit' => 'counts'},
5049
87 => +{'name' => 'max_ball_speed', 'scale' => 100, 'unit' => 'm/s'},
5050
88 => +{'name' => 'avg_ball_speed', 'scale' => 100, 'unit' => 'm/s'},
5051
89 => +{'name' => 'avg_vertical_oscillation', 'scale' => 10, 'unit' => 'mm'},
5052
90 => +{'name' => 'avg_stance_time_percent', 'scale' => 100, 'unit' => '%'},
5053
91 => +{'name' => 'avg_stance_time', 'scale' => 10, 'unit' => 'ms'},
5054
92 => +{'name' => 'avg_fractional_cadence', 'scale' => 128, 'unit' => 'rpm'},
5055
93 => +{'name' => 'max_fractional_cadence', 'scale' => 128, 'unit' => 'rpm'},
5056
94 => +{'name' => 'total_fractional_cycles', 'scale' => 128, 'unit' => 'cycles'},
5057
95 => +{'name' => 'avg_total_hemoglobin_conc', 'scale' => 100, 'unit' => 'g/dL'},
5058
96 => +{'name' => 'min_total_hemoglobin_conc', 'scale' => 100, 'unit' => 'g/dL'},
5059
97 => +{'name' => 'max_total_hemoglobin_conc', 'scale' => 100, 'unit' => 'g/dL'},
5060
98 => +{'name' => 'avg_saturated_hemoglobin_percent', 'scale' => 10, 'unit' => '%'},
5061
99 => +{'name' => 'min_saturated_hemoglobin_percent', 'scale' => 10, 'unit' => '%'},
5062
100 => +{'name' => 'max_saturated_hemoglobin_percent', 'scale' => 10, 'unit' => '%'},
5063
101 => +{'name' => 'avg_left_torque_effectiveness', 'scale' => 2, 'unit' => '%'},
5064
102 => +{'name' => 'avg_right_torque_effectiveness', 'scale' => 2, 'unit' => '%'},
5065
103 => +{'name' => 'avg_left_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5066
104 => +{'name' => 'avg_right_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5067
105 => +{'name' => 'avg_combined_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5068
106 => +{'name' => 'unknown106'}, # unknown UINT16
5069
107 => +{'name' => 'unknown107'}, # unknown UINT16
5070
108 => +{'name' => 'unknown108'}, # unknown UINT16
5071
109 => +{'name' => 'unknown109'}, # unknown UINT8
5072
110 => +{'name' => 'unknown110'}, # unknown STRING
5073
111 => +{'name' => 'sport_index'},
5074
112 => +{'name' => 'time_standing', 'scale' => 1000, 'unit' => 's'},
5075
113 => +{'name' => 'stand_count'},
5076
114 => +{'name' => 'avg_left_pco', 'unit' => 'mm'},
5077
115 => +{'name' => 'avg_right_pco', 'unit' => 'mm'},
5078
116 => +{'name' => 'avg_left_power_phase', 'scale' => 0.7111111, 'unit' => 'degrees'},
5079
117 => +{'name' => 'avg_left_power_phase_peak', 'scale' => 0.7111111, 'unit' => 'degrees'},
5080
118 => +{'name' => 'avg_right_power_phase', 'scale' => 0.7111111, 'unit' => 'degrees'},
5081
119 => +{'name' => 'avg_right_power_phase_peak', 'scale' => 0.7111111, 'unit' => 'degrees'},
5082
120 => +{'name' => 'avg_power_position', 'unit' => 'watts'},
5083
121 => +{'name' => 'max_power_position', 'unit' => 'watts'},
5084
122 => +{'name' => 'avg_cadence_position', 'unit' => 'rpm'},
5085
123 => +{'name' => 'max_cadence_position', 'unit' => 'rpm'},
5086
124 => +{'name' => 'enhanced_avg_speed', 'scale' => 1000, 'unit' => 'm/s'},
5087
125 => +{'name' => 'enhanced_max_speed', 'scale' => 1000, 'unit' => 'm/s'},
5088
126 => +{'name' => 'enhanced_avg_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5089
127 => +{'name' => 'enhanced_min_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5090
128 => +{'name' => 'enhanced_max_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5091
129 => +{'name' => 'avg_lev_motor_power', 'unit' => 'watts'},
5092
130 => +{'name' => 'max_lev_motor_power', 'unit' => 'watts'},
5093
131 => +{'name' => 'lev_battery_consumption', 'scale' => 2, 'unit' => '%'},
5094
132 => +{'name' => 'avg_vertical_ratio', 'scale' => 100, 'unit' => '%'},
5095
133 => +{'name' => 'avg_stance_time_balance', 'scale' => 100, 'unit' => '%'},
5096
134 => +{'name' => 'avg_step_length', 'scale' => 10, 'unit' => 'mm'},
5097
137 => +{'name' => 'total_anaerobic_training_effect', 'scale' => 10},
5098
139 => +{'name' => 'avg_vam', 'scale' => 1000, 'unit' => 'm/s'},
5099
140 => +{ 'name' => 'avg_depth', 'unit' => 'm', 'scale' => 1000 }, # 0 if above water
5100
141 => +{ 'name' => 'max_depth', 'unit' => 'm', 'scale' => 1000 }, # 0 if above water
5101
142 => +{ 'name' => 'surface_interval', 'unit' => 's' }, # Time since end of last dive
5102
143 => +{ 'name' => 'start_cns', 'unit' => '%' },
5103
144 => +{ 'name' => 'end_cns', 'unit' => '%' },
5104
145 => +{ 'name' => 'start_n2', 'unit' => '%' },
5105
146 => +{ 'name' => 'end_n2', 'unit' => '%' },
5106
147 => +{ 'name' => 'avg_respiration_rate' },
5107
148 => +{ 'name' => 'max_respiration_rate' },
5108
149 => +{ 'name' => 'min_respiration_rate' },
5109
150 => +{ 'name' => 'min_temperature', 'unit' => 'deg.C' },
5110
155 => +{ 'name' => 'o2_toxicity', 'unit' => 'OTUs' },
5111
156 => +{ 'name' => 'dive_number' },
5112
168 => +{ 'name' => 'training_load_peak', 'scale' => 65536 },
5113
169 => +{ 'name' => 'enhanced_avg_respiration_rate', 'unit' => 'breaths/min', 'scale' => 100 },
5114
170 => +{ 'name' => 'enhanced_max_respiration_rate', 'unit' => 'breaths/min' },
5115
180 => +{ 'name' => 'enhanced_min_respiration_rate', 'scale' => 100 },
5116
181 => +{'name' => 'total_grit', 'unit' => 'kGrit'},
5117
182 => +{'name' => 'total_flow', 'unit' => 'Flow'},
5118
183 => +{'name' => 'jump_count'},
5119
186 => +{'name' => 'avg_grit', 'unit' => 'kGrit'},
5120
187 => +{'name' => 'avg_flow', 'unit' => 'Flow'},
5121
199 => +{'name' => 'total_fractional_ascent', 'unit' => 'm'},
5122
200 => +{'name' => 'total_fractional_descent', 'unit' => 'm'},
5123
208 => +{'name' => 'avg_core_temperature', 'unit' => 'deg.C'},
5124
209 => +{'name' => 'min_core_temperature', 'unit' => 'deg.C'},
5125
210 => +{'name' => 'max_core_temperature', 'unit' => 'deg.C'},
5126
},
5127
5128
'lap' => +{
5129
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5130
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5131
0 => +{'name' => 'event', 'type_name' => 'event'},
5132
1 => +{'name' => 'event_type', 'type_name' => 'event_type'},
5133
2 => +{'name' => 'start_time', 'type_name' => 'date_time'},
5134
3 => +{'name' => 'start_position_lat', 'unit' => 'semicircles'},
5135
4 => +{'name' => 'start_position_long', 'unit' => 'semicircles'},
5136
5 => +{'name' => 'end_position_lat', 'unit' => 'semicircles'},
5137
6 => +{'name' => 'end_position_long', 'unit' => 'semicircles'},
5138
7 => +{'name' => 'total_elapsed_time', 'scale' => 1000, 'unit' => 's'},
5139
8 => +{'name' => 'total_timer_time', 'scale' => 1000, 'unit' => 's'},
5140
9 => +{'name' => 'total_distance', 'scale' => 100, 'unit' => 'm'},
5141
5142
10 => +{
5143
'name' => 'total_cycles', 'unit' => 'cycles',
5144
5145
'switch' => +{
5146
'_by' => 'sport',
5147
'walking' => +{'name' => 'total_steps', 'unit' => 'steps'},
5148
'running' => +{'name' => 'total_strides', 'unit' => 'strides'},
5149
'swimming' => +{'name' => 'total_strokes', 'unit' => 'strokes'},
5150
},
5151
},
5152
5153
11 => +{'name' => 'total_calories', 'unit' => 'kcal'},
5154
12 => +{'name' => 'total_fat_calories', 'unit' => 'kcal'},
5155
13 => +{'name' => 'avg_speed', 'scale' => 1000, 'unit' => 'm/s'},
5156
14 => +{'name' => 'max_speed', 'scale' => 1000, 'unit' => 'm/s'},
5157
15 => +{'name' => 'avg_heart_rate', 'unit' => 'bpm'},
5158
16 => +{'name' => 'max_heart_rate', 'unit' => 'bpm'},
5159
5160
17 => +{
5161
'name' => 'avg_cadence', 'unit' => 'rpm',
5162
5163
'switch' => +{
5164
'_by' => 'sport',
5165
'walking' => +{'name' => 'avg_walking_cadence', 'unit' => 'steps/min'},
5166
'running' => +{'name' => 'avg_running_cadence', 'unit' => 'strides/min'},
5167
'swimming' => +{'name' => 'avg_swimming_cadence', 'unit' => 'strokes/min'},
5168
},
5169
},
5170
5171
18 => +{
5172
'name' => 'max_cadence', 'unit' => 'rpm',
5173
5174
'switch' => +{
5175
'_by' => 'sport',
5176
'walking' => +{'name' => 'max_walking_cadence', 'unit' => 'steps/min'},
5177
'running' => +{'name' => 'max_running_cadence', 'unit' => 'strides/min'},
5178
'swimming' => +{'name' => 'max_swimming_cadence', 'unit' => 'strokes/min'},
5179
},
5180
},
5181
5182
19 => +{'name' => 'avg_power', 'unit' => 'watts'},
5183
20 => +{'name' => 'max_power', 'unit' => 'watts'},
5184
21 => +{'name' => 'total_ascent', 'unit' => 'm'},
5185
22 => +{'name' => 'total_descent', 'unit' => 'm'},
5186
23 => +{'name' => 'intensity', 'type_name' => 'intensity'},
5187
24 => +{'name' => 'lap_trigger', 'type_name' => 'lap_trigger'},
5188
25 => +{'name' => 'sport', 'type_name' => 'sport'},
5189
26 => +{'name' => 'event_group'},
5190
27 => +{'name' => 'nec_lat', 'unit' => 'semicircles'}, # not present?
5191
28 => +{'name' => 'nec_long', 'unit' => 'semicircles'}, # not present?
5192
29 => +{'name' => 'swc_lat', 'unit' => 'semicircles'}, # not present?
5193
30 => +{'name' => 'swc_long', 'unit' => 'semicircles'}, # not present?
5194
32 => +{'name' => 'num_lengths', 'unit' => 'lengths'},
5195
33 => +{'name' => 'normalized_power', 'unit' => 'watts'},
5196
34 => +{'name' => 'left_right_balance', 'type_name' => 'left_right_balance_100'},
5197
35 => +{'name' => 'first_length_index'},
5198
37 => +{'name' => 'avg_stroke_distance', 'scale' => 100, 'unit' => 'm'},
5199
38 => +{'name' => 'swim_stroke', 'type_name' => 'swim_stroke'},
5200
39 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
5201
40 => +{'name' => 'num_active_lengths', 'unit' => 'lengths'},
5202
41 => +{'name' => 'total_work', 'unit' => 'J'},
5203
42 => +{'name' => 'avg_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5204
43 => +{'name' => 'max_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5205
44 => +{'name' => 'gps_accuracy', 'unit' => 'm'},
5206
45 => +{'name' => 'avg_grade', 'scale' => 100, 'unit' => '%'},
5207
46 => +{'name' => 'avg_pos_grade', 'scale' => 100, 'unit' => '%'},
5208
47 => +{'name' => 'avg_neg_grade', 'scale' => 100, 'unit' => '%'},
5209
48 => +{'name' => 'max_pos_grade', 'scale' => 100, 'unit' => '%'},
5210
49 => +{'name' => 'max_neg_grade', 'scale' => 100, 'unit' => '%'},
5211
50 => +{'name' => 'avg_temperature', 'unit' => 'deg.C'},
5212
51 => +{'name' => 'max_temperature', 'unit' => 'deg.C'},
5213
52 => +{'name' => 'total_moving_time', 'scale' => 1000, 'unit' => 's'},
5214
53 => +{'name' => 'avg_pos_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5215
54 => +{'name' => 'avg_neg_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5216
55 => +{'name' => 'max_pos_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5217
56 => +{'name' => 'max_neg_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5218
57 => +{'name' => 'time_in_hr_zone', 'scale' => 1000, 'unit' => 's'},
5219
58 => +{'name' => 'time_in_speed_zone', 'scale' => 1000, 'unit' => 's'},
5220
59 => +{'name' => 'time_in_cadence_zone', 'scale' => 1000, 'unit' => 's'},
5221
60 => +{'name' => 'time_in_power_zone', 'scale' => 1000, 'unit' => 's'},
5222
61 => +{'name' => 'repetition_num'},
5223
62 => +{'name' => 'min_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5224
63 => +{'name' => 'min_heart_rate', 'unit' => 'bpm'},
5225
70 => +{'name' => 'unknown70'}, # unknown UINT32
5226
71 => +{'name' => 'wkt_step_index', 'type_name' => 'message_index'},
5227
72 => +{'name' => 'unknown72'}, # unknown ENUM
5228
74 => +{'name' => 'opponent_score'},
5229
75 => +{'name' => 'stroke_count', 'unit' => 'counts'},
5230
76 => +{'name' => 'zone_count', 'unit' => 'counts'},
5231
77 => +{'name' => 'avg_vertical_oscillation', 'scale' => 10, 'unit' => 'mm'},
5232
78 => +{'name' => 'avg_stance_time_percent', 'scale' => 100, 'unit' => '%'},
5233
79 => +{'name' => 'avg_stance_time', 'scale' => 10, 'unit' => 'ms'},
5234
80 => +{'name' => 'avg_fractional_cadence', 'scale' => 128, 'unit' => 'rpm'},
5235
81 => +{'name' => 'max_fractional_cadence', 'scale' => 128, 'unit' => 'rpm'},
5236
82 => +{'name' => 'total_fractional_cycles', 'scale' => 128, 'unit' => 'cycles'},
5237
83 => +{'name' => 'player_score'},
5238
84 => +{'name' => 'avg_total_hemoglobin_conc', 'scale' => 100, 'unit' => 'g/dL'},
5239
85 => +{'name' => 'min_total_hemoglobin_conc', 'scale' => 100, 'unit' => 'g/dL'},
5240
86 => +{'name' => 'max_total_hemoglobin_conc', 'scale' => 100, 'unit' => 'g/dL'},
5241
87 => +{'name' => 'avg_saturated_hemoglobin_percent', 'scale' => 10, 'unit' => '%'},
5242
88 => +{'name' => 'min_saturated_hemoglobin_percent', 'scale' => 10, 'unit' => '%'},
5243
89 => +{'name' => 'max_saturated_hemoglobin_percent', 'scale' => 10, 'unit' => '%'},
5244
91 => +{'name' => 'avg_left_torque_effectiveness', 'scale' => 2, 'unit' => '%'},
5245
92 => +{'name' => 'avg_right_torque_effectiveness', 'scale' => 2, 'unit' => '%'},
5246
93 => +{'name' => 'avg_left_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5247
94 => +{'name' => 'avg_right_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5248
95 => +{'name' => 'avg_combined_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5249
96 => +{'name' => 'unknown96'}, # unknown UINT16
5250
97 => +{'name' => 'unknown97'}, # unknown UINT16
5251
98 => +{'name' => 'time_standing', 'scale' => 1000, 'unit' => 's'},
5252
99 => +{'name' => 'stand_count'},
5253
100 => +{'name' => 'avg_left_pco', 'unit' => 'mm'},
5254
101 => +{'name' => 'avg_right_pco', 'unit' => 'mm'},
5255
102 => +{'name' => 'avg_left_power_phase', 'scale' => 0.7111111, 'unit' => 'degrees'},
5256
103 => +{'name' => 'avg_left_power_phase_peak', 'scale' => 0.7111111, 'unit' => 'degrees'},
5257
104 => +{'name' => 'avg_right_power_phase', 'scale' => 0.7111111, 'unit' => 'degrees'},
5258
105 => +{'name' => 'avg_right_power_phase_peak', 'scale' => 0.7111111, 'unit' => 'degrees'},
5259
106 => +{'name' => 'avg_power_position', 'unit' => 'watts'},
5260
107 => +{'name' => 'max_power_position', 'unit' => 'watts'},
5261
108 => +{'name' => 'avg_cadence_position', 'unit' => 'rpm'},
5262
109 => +{'name' => 'max_cadence_position', 'unit' => 'rpm'},
5263
110 => +{'name' => 'enhanced_avg_speed', 'scale' => 1000, 'unit' => 'm/s'},
5264
111 => +{'name' => 'enhanced_max_speed', 'scale' => 1000, 'unit' => 'm/s'},
5265
112 => +{'name' => 'enhanced_avg_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5266
113 => +{'name' => 'enhanced_min_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5267
114 => +{'name' => 'enhanced_max_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5268
115 => +{'name' => 'avg_lev_motor_power', 'unit' => 'watts'},
5269
116 => +{'name' => 'max_lev_motor_power', 'unit' => 'watts'},
5270
117 => +{'name' => 'lev_battery_consumption', 'scale' => 2, 'unit' => '%'},
5271
118 => +{'name' => 'avg_vertical_ratio', 'scale' => 100, 'unit' => '%'},
5272
119 => +{'name' => 'avg_stance_time_balance', 'scale' => 100, 'unit' => '%'},
5273
120 => +{'name' => 'avg_step_length', 'scale' => 10, 'unit' => 'mm'},
5274
121 => +{'name' => 'avg_vam', 'scale' => 1000, 'unit' => 'm/s'},
5275
122 => +{ 'name' => 'avg_depth', 'unit' => 'm', 'scale' => 1000 }, # 0 if above water
5276
123 => +{ 'name' => 'max_depth', 'unit' => 'm', 'scale' => 1000 }, # 0 if above water
5277
124 => +{ 'name' => 'min_temperature', 'unit' => 'deg.C' },
5278
136 => +{ 'name' => 'enhanced_avg_respiration_rate', 'unit' => 'breaths/min', 'scale' => 100 },
5279
137 => +{ 'name' => 'enhanced_max_respiration_rate', 'unit' => 'breaths/min', 'scale' => 100 },
5280
147 => +{ 'name' => 'avg_respiration_rate' },
5281
148 => +{ 'name' => 'max_respiration_rate' },
5282
149 => +{'name' => 'total_grit', 'unit' => 'kGrit'},
5283
150 => +{'name' => 'total_flow', 'unit' => 'Flow'},
5284
151 => +{'name' => 'jump_count'},
5285
153 => +{'name' => 'avg_grit', 'unit' => 'kGrit'},
5286
154 => +{'name' => 'avg_flow', 'unit' => 'Flow'},
5287
156 => +{'name' => 'total_fractional_ascent', 'unit' => 'm'},
5288
157 => +{'name' => 'total_fractional_descent', 'unit' => 'm'},
5289
158 => +{'name' => 'avg_core_temperature', 'unit' => 'deg.C'},
5290
159 => +{'name' => 'min_core_temperature', 'unit' => 'deg.C'},
5291
160 => +{'name' => 'max_core_temperature', 'unit' => 'deg.C'},
5292
},
5293
5294
'length' => +{
5295
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5296
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5297
0 => +{'name' => 'event', 'type_name' => 'event'},
5298
1 => +{'name' => 'event_type', 'type_name' => 'event_type'},
5299
2 => +{'name' => 'start_time', 'type_name' => 'date_time'},
5300
3 => +{'name' => 'total_elapsed_time', 'scale' => 1000, 'unit' => 's'},
5301
4 => +{'name' => 'total_timer_time', 'scale' => 1000, 'unit' => 's'},
5302
5 => +{'name' => 'total_strokes', 'unit' => 'strokes'},
5303
6 => +{'name' => 'avg_speed', 'scale' => 1000, 'unit' => 'm/s'},
5304
7 => +{'name' => 'swim_stroke', 'type_name' => 'swim_stroke'},
5305
9 => +{'name' => 'avg_swimming_cadence', 'unit' => 'strokes/min'},
5306
10 => +{'name' => 'event_group'},
5307
11 => +{'name' => 'total_calories', 'unit' => 'kcal'},
5308
12 => +{'name' => 'length_type', 'type_name' => 'length_type'},
5309
18 => +{'name' => 'player_score'},
5310
19 => +{'name' => 'opponent_score'},
5311
20 => +{'name' => 'stroke_count', 'unit' => 'counts'},
5312
21 => +{'name' => 'zone_count', 'unit' => 'counts'},
5313
22 => +{ 'name' => 'enhanced_avg_respiration_rate', 'unit' => 'breaths/min', 'scale' => 100 },
5314
23 => +{ 'name' => 'enhanced_max_respiration_rate', 'unit' => 'breaths/min', 'scale' => 100 },
5315
24 => +{ 'name' => 'avg_respiration_rate' },
5316
25 => +{ 'name' => 'max_respiration_rate' },
5317
},
5318
5319
'record' => +{
5320
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5321
0 => +{'name' => 'position_lat', 'unit' => 'semicircles'},
5322
1 => +{'name' => 'position_long', 'unit' => 'semicircles'},
5323
2 => +{'name' => 'altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5324
3 => +{'name' => 'heart_rate', 'unit' => 'bpm'},
5325
4 => +{'name' => 'cadence', 'unit' => 'rpm'},
5326
5 => +{'name' => 'distance', 'scale' => 100, 'unit' => 'm'},
5327
6 => +{'name' => 'speed', 'scale' => 1000, 'unit' => 'm/s'},
5328
7 => +{'name' => 'power', 'unit' => 'watts'},
5329
8 => +{'name' => 'compressed_speed_distance'}, # complex decoding!
5330
9 => +{'name' => 'grade', 'scale' => 100, 'unit' => '%'},
5331
10 => +{'name' => 'resistance'},
5332
11 => +{'name' => 'time_from_course', 'scale' => 1000, 'unit' => 's'},
5333
12 => +{'name' => 'cycle_length', 'scale' => 100, 'unit' => 'm'},
5334
13 => +{'name' => 'temperature', 'unit' => 'deg.C'},
5335
17 => +{'name' => 'speed_1s', 'scale' => 16, 'unit' => 'm/s'},
5336
18 => +{'name' => 'cycles', 'unit' => 'cycles'},
5337
19 => +{'name' => 'total_cycles', 'unit' => 'cycles'},
5338
28 => +{'name' => 'compressed_accumulated_power', 'unit' => 'watts'},
5339
29 => +{'name' => 'accumulated_power', 'unit' => 'watts'},
5340
30 => +{'name' => 'left_right_balance', 'type_name' => 'left_right_balance'},
5341
31 => +{'name' => 'gps_accuracy', 'unit' => 'm'},
5342
32 => +{'name' => 'vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5343
33 => +{'name' => 'calories', 'unit' => 'kcal'},
5344
39 => +{'name' => 'vertical_oscillation', 'scale' => 10, 'unit' => 'mm'},
5345
40 => +{'name' => 'stance_time_percent', 'scale' => 100, 'unit' => '%'},
5346
41 => +{'name' => 'stance_time', 'scale' => 10, 'unit' => 'ms'},
5347
42 => +{'name' => 'activity_type', 'type_name' => 'activity_type'},
5348
43 => +{'name' => 'left_torque_effectiveness', 'scale' => 2, 'unit' => '%'},
5349
44 => +{'name' => 'right_torque_effectiveness', 'scale' => 2, 'unit' => '%'},
5350
45 => +{'name' => 'left_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5351
46 => +{'name' => 'right_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5352
47 => +{'name' => 'combined_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5353
48 => +{'name' => 'time128', 'scale' => 128, 'unit' => 's'},
5354
49 => +{'name' => 'stroke_type', 'type_name' => 'stroke_type'},
5355
50 => +{'name' => 'zone'},
5356
51 => +{'name' => 'ball_speed', 'scale' => 100, 'unit' => 'm/s'},
5357
52 => +{'name' => 'cadence256', 'scale' => 256, 'unit' => 'rpm'},
5358
53 => +{'name' => 'fractional_cadence', 'scale' => 128, 'unit' => 'rpm'},
5359
54 => +{'name' => 'total_hemoglobin_conc', 'scale' => 100, 'unit' => 'g/dL'},
5360
55 => +{'name' => 'total_hemoglobin_conc_min', 'scale' => 100, 'unit' => 'g/dL'},
5361
56 => +{'name' => 'total_hemoglobin_conc_max', 'scale' => 100, 'unit' => 'g/dL'},
5362
57 => +{'name' => 'saturated_hemoglobin_percent', 'scale' => 10, 'unit' => '%'},
5363
58 => +{'name' => 'saturated_hemoglobin_percent_min', 'scale' => 10, 'unit' => '%'},
5364
59 => +{'name' => 'saturated_hemoglobin_percent_max', 'scale' => 10, 'unit' => '%'},
5365
61 => +{'name' => 'unknown61'}, # unknown UINT16
5366
62 => +{'name' => 'device_index', 'type_name' => 'device_index'},
5367
66 => +{'name' => 'unknown66'}, # unknown SINT16
5368
67 => +{'name' => 'left_pco', 'unit' => 'mm'},
5369
68 => +{'name' => 'right_pco', 'unit' => 'mm'},
5370
69 => +{'name' => 'left_power_phase', 'scale' => 0.7111111, 'unit' => 'degrees'},
5371
70 => +{'name' => 'left_power_phase_peak', 'scale' => 0.7111111, 'unit' => 'degrees'},
5372
71 => +{'name' => 'right_power_phase', 'scale' => 0.7111111, 'unit' => 'degrees'},
5373
72 => +{'name' => 'right_power_phase_peak', 'scale' => 0.7111111, 'unit' => 'degrees'},
5374
73 => +{'name' => 'enhanced_speed', 'scale' => 1000, 'unit' => 'm/s'},
5375
78 => +{'name' => 'enhanced_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5376
81 => +{'name' => 'battery_soc', 'scale' => 2, 'unit' => '%'},
5377
82 => +{'name' => 'motor_power', 'unit' => 'watts'},
5378
83 => +{'name' => 'vertical_ratio', 'scale' => 100, 'unit' => '%'},
5379
84 => +{'name' => 'stance_time_balance', 'scale' => 100, 'unit' => '%'},
5380
85 => +{'name' => 'step_length', 'scale' => 10, 'unit' => 'mm'},
5381
91 => +{'name' => 'absolute_pressure', 'unit' => 'Pa'},
5382
92 => +{'name' => 'depth', 'scale' => 1000, 'unit' => 'm'},
5383
93 => +{'name' => 'next_stop_depth', 'scale' => 1000, 'unit' => 'm'},
5384
94 => +{'name' => 'next_stop_time', 'unit' => 's'},
5385
95 => +{'name' => 'time_to_surface', 'unit' => 's'},
5386
96 => +{'name' => 'ndl_time', 'unit' => 's'},
5387
97 => +{'name' => 'cns_load', 'unit' => '%'},
5388
98 => +{'name' => 'n2_load', 'unit' => '%'},
5389
99 => +{ 'name' => 'respiration_rate' },
5390
108 => +{ 'name' => 'enhanced_respiration_rate', 'unit' => 'breaths/min', 'scale' => 100 },
5391
114 => +{'name' => 'grit'},
5392
115 => +{'name' => 'flow'},
5393
117 => +{'name' => 'ebike_travel_range', 'unit' => 'km'},
5394
118 => +{'name' => 'ebike_battery_level', 'unit' => '%'},
5395
119 => +{'name' => 'ebike_assist_mode'},
5396
120 => +{'name' => 'ebike_assist_level_percent', 'unit' => '%'},
5397
123 => +{ 'name' => 'air_time_remaining' },
5398
124 => +{ 'name' => 'pressure_sac', 'unit' => 'bar/min', 'scale' => 100 }, # Pressure-based surface air consumption
5399
125 => +{ 'name' => 'volume_sac', 'unit' => 'l/min', 'scale' => 100 }, # Volumetric surface air consumption
5400
126 => +{ 'name' => 'rmv', 'unit' => 'l/min', 'scale' => 100 }, # Respiratory minute volume
5401
127 => +{ 'name' => 'ascent_rate', 'unit' => 'm/s', 'scale' => 1000 },
5402
129 => +{ 'name' => 'po2', 'unit' => 'percent', 'scale' => 100 }, # Current partial pressure of oxygen
5403
139 => +{'name' => 'core_temperature', 'scale' => 100, 'unit' => 'deg.C'},
5404
},
5405
5406
'event' => +{
5407
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5408
0 => +{'name' => 'event', 'type_name' => 'event'},
5409
1 => +{'name' => 'event_type', 'type_name' => 'event_type'},
5410
2 => +{'name' => 'data16'}, # no switch?
5411
5412
3 => +{
5413
'name' => 'data',
5414
5415
'switch' => +{
5416
'_by' => 'event',
5417
'timer' => +{'name' => 'timer_trigger', 'type_name' => 'timer_trigger'},
5418
'course_point' => +{'name' => 'course_point_index', 'type_name' => 'message_index'},
5419
'battery' => +{'name' => 'battery_level', 'scale' => 1000, 'unit' => 'V'},
5420
'virtual_partner_pace' => +{'name' => 'virtual_partner_speed', 'scale' => 1000, 'unit' => 'm/s'},
5421
'hr_high_alert' => +{'name' => 'hr_high_alert', 'unit' => 'bpm'},
5422
'hr_low_alert' => +{'name' => 'hr_low_alert', 'unit' => 'bpm'},
5423
'speed_high_alert' => +{'name' => 'speed_high_alert', 'scale' => 1000, 'unit' => 'm/s'},
5424
'speed_low_alert' => +{'name' => 'speed_low_alert', 'scale' => 1000, 'unit' => 'm/s'},
5425
'cad_high_alert' => +{'name' => 'cad_high_alert', 'unit' => 'rpm'},
5426
'cad_low_alert' => +{'name' => 'cad_low_alert', 'unit' => 'rpm'},
5427
'power_high_alert' => +{'name' => 'power_high_alert', 'unit' => 'watts'},
5428
'power_low_alert' => +{'name' => 'power_low_alert', 'unit' => 'watts'},
5429
'time_duration_alert' => +{'name' => 'time_duration_alert', 'scale' => 1000, 'unit' => 's'},
5430
'distance_duration_alert' => +{'name' => 'distance_duration_alert', 'scale' => 100, 'unit' => 'm'},
5431
'calorie_duration_alert' => +{'name' => 'calorie_duration_alert', 'unit' => 'kcal'},
5432
# why is this key not the same as the name?
5433
'fitness_equipment' => +{'name' => 'fitness_equipment_state', 'type_name' => 'fitness_equipment_state'},
5434
'sport_point' => +{'name' => 'sport_point', 'scale' => 11}, # complex decoding!
5435
'front_gear_change' => +{'name' => 'gear_change_data', 'scale' => 1111}, # complex decoding!
5436
'rear_gear_change' => +{'name' => 'gear_change_data', 'scale' => 1111}, # complex decoding!
5437
'rider_position_change' => +{'name' => 'rider_position', 'type_name' => 'rider_position_type'},
5438
'comm_timeout' => +{'name' => 'comm_timeout', 'type_name' => 'comm_timeout_type'},
5439
'dive_alert' => +{ 'name' => 'dive_alert', 'type_name' => 'dive_alert' },
5440
'radar_threat_alert' => +{'name' => 'radar_threat_alert'},
5441
},
5442
},
5443
5444
4 => +{'name' => 'event_group'},
5445
7 => +{'name' => 'score'},
5446
8 => +{'name' => 'opponent_score'},
5447
9 => +{'name' => 'front_gear_num'},
5448
10 => +{'name' => 'front_gear'},
5449
11 => +{'name' => 'rear_gear_num'},
5450
12 => +{'name' => 'rear_gear'},
5451
13 => +{'name' => 'device_index', 'type_name' => 'device_index'},
5452
21 => +{'name' => 'radar_threat_level_max', 'type_name' => 'radar_threat_level_type'},
5453
22 => +{'name' => 'radar_threat_count'},
5454
23 => +{'name' => 'radar_threat_avg_approach_speed', unit => 'm/s'},
5455
24 => +{'name' => 'radar_threat_max_approach_speed', unit => 'm/s'},
5456
},
5457
5458
'device_info' => +{
5459
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5460
0 => +{'name' => 'device_index', 'type_name' => 'device_index'},
5461
5462
1 => +{
5463
'name' => 'device_type',
5464
5465
'switch' => +{
5466
'_by' => 'source_type',
5467
'bluetooth_low_energy' => +{ 'name' => 'ble_device_type', 'type_name' => 'ble_device_type' },
5468
'antplus' => +{'name' => 'antplus_device_type', 'type_name' => 'antplus_device_type'},
5469
'ant' => +{'name' => 'ant_device_type'},
5470
'local' => +{'name' => 'local_device_type', 'type_name' => 'local_device_type'},
5471
},
5472
},
5473
5474
2 => +{'name' => 'manufacturer', 'type_name' => 'manufacturer'},
5475
3 => +{'name' => 'serial_number'},
5476
5477
4 => +{
5478
'name' => 'product',
5479
5480
'switch' => +{
5481
'_by' => 'manufacturer',
5482
'garmin' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
5483
'dynastream' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
5484
'dynastream_oem' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
5485
'favero_electronics' => +{'name' => 'favero_product', 'type_name' => 'favero_product'},
5486
'tacx' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
5487
},
5488
},
5489
5490
5 => +{'name' => 'software_version', 'scale' => 100},
5491
6 => +{'name' => 'hardware_version'},
5492
7 => +{'name' => 'cum_operating_time', 'unit' => 's'},
5493
8 => +{'name' => 'unknown8'}, # unknown UINT32
5494
9 => +{'name' => 'unknown9'}, # unknown UINT8
5495
10 => +{'name' => 'battery_voltage', 'scale' => 256, 'unit' => 'V'},
5496
11 => +{'name' => 'battery_status', 'type_name' => 'battery_status'},
5497
15 => +{'name' => 'unknown15'}, # unknown UINT32
5498
16 => +{'name' => 'unknown16'}, # unknown UINT32
5499
18 => +{'name' => 'sensor_position', 'type_name' => 'body_location'},
5500
19 => +{'name' => 'descriptor'},
5501
20 => +{'name' => 'ant_transmission_type'},
5502
21 => +{'name' => 'ant_device_number'},
5503
22 => +{'name' => 'ant_network', 'type_name' => 'ant_network'},
5504
24 => +{'name' => 'unknown24'}, # unknown UINT32Z
5505
25 => +{'name' => 'source_type', 'type_name' => 'source_type'},
5506
27 => +{'name' => 'product_name'},
5507
32 => +{'name' => 'battery_level', 'unit' => '%'},
5508
},
5509
5510
'device_aux_battery_info' => +{
5511
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5512
0 => +{'name' => 'device_index', 'type_name' => 'device_index'},
5513
1 => +{'name' => 'battery_voltage', 'scale' => 256, 'unit' => 'V'},
5514
2 => +{'name' => 'battery_status', 'type_name' => 'battery_status'},
5515
},
5516
5517
'training_file' => +{
5518
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5519
0 => +{'name' => 'type', 'type_name' => 'file'},
5520
1 => +{'name' => 'manufacturer', 'type_name' => 'manufacturer'},
5521
5522
2 => +{
5523
'name' => 'product',
5524
5525
'switch' => +{
5526
'_by' => 'manufacturer',
5527
'garmin' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
5528
'dynastream' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
5529
'dynastream_oem' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
5530
'favero_electronics' => +{'name' => 'favero_product', 'type_name' => 'favero_product'},
5531
'tacx' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
5532
},
5533
},
5534
5535
3 => +{'name' => 'serial_number'},
5536
4 => +{'name' => 'time_created', 'type_name' => 'date_time'},
5537
},
5538
5539
'weather_conditions' => +{
5540
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5541
0 => +{'name' => 'weather_report', 'type_name' => 'weather_report'},
5542
1 => +{'name' => 'temperature', 'unit' => 'deg.C'},
5543
2 => +{'name' => 'condition', 'type_name' => 'weather_status'},
5544
3 => +{'name' => 'wind_direction', 'unit' => 'degrees'},
5545
4 => +{'name' => 'wind_speed', 'scale' => 1000, 'unit' => 'm/s'},
5546
5 => +{'name' => 'precipitation_probability'},
5547
6 => +{'name' => 'temperature_feels_like', 'unit' => 'deg.C'},
5548
7 => +{'name' => 'relative_humidity', 'unit' => '%'},
5549
8 => +{'name' => 'location'},
5550
9 => +{'name' => 'observed_at_time', 'type_name' => 'date_time'},
5551
10 => +{'name' => 'observed_location_lat', 'unit' => 'semicircles'},
5552
11 => +{'name' => 'observed_location_long', 'unit' => 'semicircles'},
5553
12 => +{'name' => 'day_of_week', 'type_name' => 'day_of_week'},
5554
13 => +{'name' => 'high_temperature', 'unit' => 'deg.C'},
5555
14 => +{'name' => 'low_temperature', 'unit' => 'deg.C'},
5556
},
5557
5558
'weather_alert' => +{
5559
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5560
0 => +{'name' => 'report_id'},
5561
1 => +{'name' => 'issue_time', 'type_name' => 'date_time'},
5562
2 => +{'name' => 'expire_time', 'type_name' => 'date_time'},
5563
3 => +{'name' => 'severity', 'type_name' => 'weather_severity'},
5564
4 => +{'name' => 'type', 'type_name' => 'weather_severe_type'},
5565
},
5566
5567
'gps_metadata' => +{
5568
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5569
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5570
1 => +{'name' => 'position_lat', 'unit' => 'semicircles'},
5571
2 => +{'name' => 'position_long', 'unit' => 'semicircles'},
5572
3 => +{'name' => 'enhanced_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5573
4 => +{'name' => 'enhanced_speed', 'scale' => 1000, 'unit' => 'm/s'},
5574
5 => +{'name' => 'heading', 'scale' => 100, 'unit' => 'degrees'},
5575
6 => +{'name' => 'utc_timestamp', 'type_name' => 'date_time'},
5576
7 => +{'name' => 'velocity', 'scale' => 100, 'unit' => 'm/s'},
5577
},
5578
5579
'camera_event' => +{
5580
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5581
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5582
1 => +{'name' => 'camera_event_type', 'type_name' => 'camera_event_type'},
5583
2 => +{'name' => 'camera_file_uuid'},
5584
3 => +{'name' => 'camera_orientation', 'type_name' => 'camera_orientation_type'},
5585
},
5586
5587
'gyroscope_data' => +{
5588
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5589
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5590
1 => +{'name' => 'sample_time_offset', 'unit' => 'ms'},
5591
2 => +{'name' => 'gyro_x', 'unit' => 'counts'},
5592
3 => +{'name' => 'gyro_y', 'unit' => 'counts'},
5593
4 => +{'name' => 'gyro_z', 'unit' => 'counts'},
5594
5 => +{'name' => 'calibrated_gyro_x', 'unit' => 'deg/s'},
5595
6 => +{'name' => 'calibrated_gyro_y', 'unit' => 'deg/s'},
5596
7 => +{'name' => 'calibrated_gyro_z', 'unit' => 'deg/s'},
5597
},
5598
5599
'accelerometer_data' => +{
5600
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5601
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5602
1 => +{'name' => 'sample_time_offset', 'unit' => 'ms'},
5603
2 => +{'name' => 'accel_x', 'unit' => 'counts'},
5604
3 => +{'name' => 'accel_y', 'unit' => 'counts'},
5605
4 => +{'name' => 'accel_z', 'unit' => 'counts'},
5606
5 => +{'name' => 'calibrated_accel_x', 'unit' => 'g'},
5607
6 => +{'name' => 'calibrated_accel_y', 'unit' => 'g'},
5608
7 => +{'name' => 'calibrated_accel_z', 'unit' => 'g'},
5609
8 => +{'name' => 'compressed_calibrated_accel_x', 'unit' => 'mG'},
5610
9 => +{'name' => 'compressed_calibrated_accel_y', 'unit' => 'mG'},
5611
10 => +{'name' => 'compressed_calibrated_accel_z', 'unit' => 'mG'},
5612
},
5613
5614
'magnetometer_data' => +{
5615
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5616
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5617
1 => +{'name' => 'sample_time_offset', 'unit' => 'ms'},
5618
2 => +{'name' => 'mag_x', 'unit' => 'counts'},
5619
3 => +{'name' => 'mag_y', 'unit' => 'counts'},
5620
4 => +{'name' => 'mag_z', 'unit' => 'counts'},
5621
5 => +{'name' => 'calibrated_mag_x', 'unit' => 'G'},
5622
6 => +{'name' => 'calibrated_mag_y', 'unit' => 'G'},
5623
7 => +{'name' => 'calibrated_mag_z', 'unit' => 'G'},
5624
},
5625
5626
'barometer_data' => +{
5627
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5628
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5629
1 => +{'name' => 'sample_time_offset', 'unit' => 'ms'},
5630
2 => +{'name' => 'baro_pres', 'unit' => 'Pa'},
5631
},
5632
5633
'three_d_sensor_calibration' => +{
5634
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5635
0 => +{'name' => 'sensor_type', 'type_name' => 'sensor_type'},
5636
5637
1 => +{
5638
'name' => 'calibration_factor',
5639
5640
'switch' => +{
5641
'_by' => 'sensor_type',
5642
'accelerometer' => +{'name' => 'accel_cal_factor'},
5643
'gyroscope' => +{'name' => 'gyro_cal_factor'},
5644
},
5645
},
5646
5647
2 => +{'name' => 'calibration_divisor', 'unit' => 'counts'},
5648
3 => +{'name' => 'level_shift'},
5649
4 => +{'name' => 'offset_cal'},
5650
5 => +{'name' => 'orientation_matrix', 'scale' => 65535},
5651
},
5652
5653
'one_d_sensor_calibration' => +{
5654
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5655
0 => +{'name' => 'sensor_type', 'type_name' => 'sensor_type'},
5656
5657
1 => +{
5658
'name' => 'calibration_factor',
5659
5660
'switch' => +{
5661
'_by' => 'sensor_type',
5662
'barometer' => +{'name' => 'baro_cal_factor'},
5663
},
5664
},
5665
5666
2 => +{'name' => 'calibration_divisor', 'unit' => 'counts'},
5667
3 => +{'name' => 'level_shift'},
5668
4 => +{'name' => 'offset_cal'},
5669
},
5670
5671
'video_frame' => +{
5672
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5673
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5674
1 => +{'name' => 'frame_number'},
5675
},
5676
5677
'obdii_data' => +{
5678
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5679
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5680
1 => +{'name' => 'time_offset', 'unit' => 'ms'},
5681
2 => +{'name' => 'pid'},
5682
3 => +{'name' => 'raw_data'},
5683
4 => +{'name' => 'pid_data_size'},
5684
5 => +{'name' => 'system_time'},
5685
6 => +{'name' => 'start_timestamp', 'type_name' => 'date_time'},
5686
7 => +{'name' => 'start_timestamp_ms', 'unit' => 'ms'},
5687
},
5688
5689
'nmea_sentence' => +{
5690
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5691
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5692
1 => +{'name' => 'sentence'},
5693
},
5694
5695
'aviation_attitude' => +{
5696
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5697
0 => +{'name' => 'timestamp_ms', 'unit' => 'ms'},
5698
1 => +{'name' => 'system_time', 'unit' => 'ms'},
5699
2 => +{'name' => 'pitch', 'scale' => 10430.38, 'unit' => 'radians'},
5700
3 => +{'name' => 'roll', 'scale' => 10430.38, 'unit' => 'radians'},
5701
4 => +{'name' => 'accel_lateral', 'scale' => 100, 'unit' => 'm/s^2'},
5702
5 => +{'name' => 'accel_normal', 'scale' => 100, 'unit' => 'm/s^2'},
5703
6 => +{'name' => 'turn_rate', 'scale' => 1024, 'unit' => 'radians/second'},
5704
7 => +{'name' => 'stage', 'type_name' => 'attitude_stage'},
5705
8 => +{'name' => 'attitude_stage_complete', 'unit' => '%'},
5706
9 => +{'name' => 'track', 'scale' => 10430.38, 'unit' => 'radians'},
5707
10 => +{'name' => 'validity', 'type_name' => 'attitude_validity'},
5708
},
5709
5710
'video' => +{
5711
0 => +{'name' => 'url'},
5712
1 => +{'name' => 'hosting_provider'},
5713
2 => +{'name' => 'duration', 'unit' => 'ms'},
5714
},
5715
5716
'video_title' => +{
5717
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5718
0 => +{'name' => 'message_count'},
5719
1 => +{'name' => 'text'},
5720
},
5721
5722
'video_description' => +{
5723
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5724
0 => +{'name' => 'message_count'},
5725
1 => +{'name' => 'text'},
5726
},
5727
5728
'video_clip' => +{
5729
0 => +{'name' => 'clip_number'},
5730
1 => +{'name' => 'start_timestamp', 'type_name' => 'date_time'},
5731
2 => +{'name' => 'start_timestamp_ms', 'unit' => 'ms'},
5732
3 => +{'name' => 'end_timestamp', 'type_name' => 'date_time'},
5733
4 => +{'name' => 'end_timestamp_ms', 'unit' => 'ms'},
5734
6 => +{'name' => 'clip_start', 'unit' => 'ms'},
5735
7 => +{'name' => 'clip_end', 'unit' => 'ms'},
5736
},
5737
5738
'set' => +{
5739
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5740
0 => +{'name' => 'duration', 'scale' => 1000, 'unit' => 's'},
5741
3 => +{'name' => 'repetitions'},
5742
4 => +{'name' => 'weight', 'scale' => 16, 'unit' => 'kg'},
5743
5 => +{'name' => 'set_type', 'type_name' => 'set_type'},
5744
6 => +{'name' => 'start_time', 'type_name' => 'date_time'},
5745
7 => +{'name' => 'category', 'type_name' => 'exercise_category'},
5746
8 => +{'name' => 'category_subtype'},
5747
9 => +{'name' => 'weight_display_unit', 'type_name' => 'fit_base_unit'},
5748
10 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5749
11 => +{'name' => 'wkt_step_index', 'type_name' => 'message_index'},
5750
},
5751
5752
'jump' => +{
5753
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5754
0 => +{'name' => 'distance', 'unit' => 'm'},
5755
1 => +{'name' => 'height', 'unit' => 'm'},
5756
2 => +{'name' => 'rotations'},
5757
3 => +{'name' => 'hang_time', 'unit' => 's'},
5758
4 => +{'name' => 'score'},
5759
5 => +{'name' => 'position_lat', 'unit' => 'semicircles'},
5760
6 => +{'name' => 'position_long', 'unit' => 'semicircles'},
5761
7 => +{'name' => 'speed', 'scale' => 1000, 'unit' => 'm/s'},
5762
8 => +{'name' => 'enhanced_speed', 'scale' => 1000, 'unit' => 'm/s'},
5763
},
5764
5765
'split' => +{
5766
0 => +{ 'name' => 'split_type', 'type_name' => 'split_type' },
5767
1 => +{ 'name' => 'total_elapsed_time', 'unit' => 's', 'scale' => 1000 },
5768
2 => +{ 'name' => 'total_timer_time', 'unit' => 's', 'scale' => 1000 },
5769
3 => +{ 'name' => 'total_distance', 'unit' => 'm', 'scale' => 100 },
5770
9 => +{ 'name' => 'start_time', 'type_name' => 'date_time' },
5771
},
5772
5773
'climb_pro' => +{
5774
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5775
0 => +{'name' => 'position_lat', 'unit' => 'semicircles'},
5776
1 => +{'name' => 'position_long', 'unit' => 'semicircles'},
5777
2 => +{'name' => 'climb_pro_event', 'type_name' => 'climb_pro_event'},
5778
3 => +{'name' => 'climb_number'},
5779
4 => +{'name' => 'climb_category'},
5780
5 => +{'name' => 'current_dist', 'unit' => 'm'},
5781
},
5782
5783
'field_description' => +{
5784
0 => +{'name' => 'developer_data_index'},
5785
1 => +{'name' => 'field_definition_number'},
5786
2 => +{'name' => 'fit_base_type_id', 'type_name' => 'fit_base_type'},
5787
3 => +{'name' => 'field_name'},
5788
4 => +{'name' => 'array'},
5789
5 => +{'name' => 'components'},
5790
6 => +{'name' => 'scale'},
5791
7 => +{'name' => 'offset'},
5792
8 => +{'name' => 'units'},
5793
9 => +{'name' => 'bits'},
5794
10 => +{'name' => 'accumulate'},
5795
13 => +{'name' => 'fit_base_unit_id', 'type_name' => 'fit_base_unit'},
5796
14 => +{'name' => 'native_mesg_num', 'type_name' => 'mesg_num'},
5797
15 => +{'name' => 'native_field_num'},
5798
},
5799
5800
'developer_data_id' => +{
5801
0 => +{'name' => 'developer_id'},
5802
1 => +{'name' => 'application_id'},
5803
2 => +{'name' => 'manufacturer_id', 'type_name' => 'manufacturer'},
5804
3 => +{'name' => 'developer_data_index'},
5805
4 => +{'name' => 'application_version'},
5806
},
5807
5808
'course' => +{ # begins === Course file messages === section
5809
4 => +{'name' => 'sport', 'type_name' => 'sport'},
5810
5 => +{'name' => 'name'},
5811
6 => +{'name' => 'capabilities', 'type_name' => 'course_capabilities'},
5812
7 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
5813
},
5814
5815
'course_point' => +{
5816
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5817
1 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5818
2 => +{'name' => 'position_lat', 'unit' => 'semicircles'},
5819
3 => +{'name' => 'position_long', 'unit' => 'semicircles'},
5820
4 => +{'name' => 'distance', 'scale' => 100, 'unit' => 'm'},
5821
5 => +{'name' => 'type', 'type_name' => 'course_point'},
5822
6 => +{'name' => 'name'},
5823
8 => +{'name' => 'favorite', 'type_name' => 'bool'},
5824
},
5825
5826
'segment_id' => +{ # begins === Segment file messages === section
5827
0 => +{'name' => 'name'},
5828
1 => +{'name' => 'uuid'},
5829
2 => +{'name' => 'sport', 'type_name' => 'sport'},
5830
3 => +{'name' => 'enabled', 'type_name' => 'bool'},
5831
4 => +{'name' => 'user_profile_primary_key'},
5832
5 => +{'name' => 'device_id'},
5833
6 => +{'name' => 'default_race_leader'},
5834
7 => +{'name' => 'delete_status', 'type_name' => 'segment_delete_status'},
5835
8 => +{'name' => 'selection_type', 'type_name' => 'segment_selection_type'},
5836
},
5837
5838
'segment_leaderboard_entry' => +{
5839
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5840
0 => +{'name' => 'name'},
5841
1 => +{'name' => 'type', 'type_name' => 'segment_leaderboard_type'},
5842
2 => +{'name' => 'group_primary_key'},
5843
3 => +{'name' => 'activity_id'},
5844
4 => +{'name' => 'segment_time', 'scale' => 1000, 'unit' => 's'},
5845
5 => +{'name' => 'activity_id_string'},
5846
},
5847
5848
'segment_point' => +{
5849
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5850
1 => +{'name' => 'position_lat', 'unit' => 'semicircles'},
5851
2 => +{'name' => 'position_long', 'unit' => 'semicircles'},
5852
3 => +{'name' => 'distance', 'scale' => 100, 'unit' => 'm'},
5853
4 => +{'name' => 'altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5854
5 => +{'name' => 'leader_time', 'scale' => 1000, 'unit' => 's'},
5855
6 => +{ 'name' => 'enhanced_altitude', 'unit' => 'm', 'scale' => 5 }, # Accumulated altitude along the segment at the described point
5856
},
5857
5858
'segment_lap' => +{
5859
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5860
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
5861
0 => +{'name' => 'event', 'type_name' => 'event'},
5862
1 => +{'name' => 'event_type', 'type_name' => 'event_type'},
5863
2 => +{'name' => 'start_time', 'type_name' => 'date_time'},
5864
3 => +{'name' => 'start_position_lat', 'unit' => 'semicircles'},
5865
4 => +{'name' => 'start_position_long', 'unit' => 'semicircles'},
5866
5 => +{'name' => 'end_position_lat', 'unit' => 'semicircles'},
5867
6 => +{'name' => 'end_position_long', 'unit' => 'semicircles'},
5868
7 => +{'name' => 'total_elapsed_time', 'scale' => 1000, 'unit' => 's'},
5869
8 => +{'name' => 'total_timer_time', 'scale' => 1000, 'unit' => 's'},
5870
9 => +{'name' => 'total_distance', 'scale' => 100, 'unit' => 'm'},
5871
5872
10 => +{
5873
'name' => 'total_cycles', 'unit' => 'cycles',
5874
5875
'switch' => +{
5876
'_by' => 'sport',
5877
'walking' => +{'name' => 'total_steps', 'unit' => 'steps'},
5878
'running' => +{'name' => 'total_strides', 'unit' => 'strides'},
5879
'swimming' => +{'name' => 'total_strokes', 'unit' => 'strokes'},
5880
},
5881
},
5882
5883
11 => +{'name' => 'total_calories', 'unit' => 'kcal'},
5884
12 => +{'name' => 'total_fat_calories', 'unit' => 'kcal'},
5885
13 => +{'name' => 'avg_speed', 'scale' => 1000, 'unit' => 'm/s'},
5886
14 => +{'name' => 'max_speed', 'scale' => 1000, 'unit' => 'm/s'},
5887
15 => +{'name' => 'avg_heart_rate', 'unit' => 'bpm'},
5888
16 => +{'name' => 'max_heart_rate', 'unit' => 'bpm'},
5889
17 => +{'name' => 'avg_cadence', 'unit' => 'rpm'},
5890
18 => +{'name' => 'max_cadence', 'unit' => 'rpm'},
5891
19 => +{'name' => 'avg_power', 'unit' => 'watts'},
5892
20 => +{'name' => 'max_power', 'unit' => 'watts'},
5893
21 => +{'name' => 'total_ascent', 'unit' => 'm'},
5894
22 => +{'name' => 'total_descent', 'unit' => 'm'},
5895
23 => +{'name' => 'sport', 'type_name' => 'sport'},
5896
24 => +{'name' => 'event_group'},
5897
25 => +{'name' => 'nec_lat', 'unit' => 'semicircles'},
5898
26 => +{'name' => 'nec_long', 'unit' => 'semicircles'},
5899
27 => +{'name' => 'swc_lat', 'unit' => 'semicircles'},
5900
28 => +{'name' => 'swc_long', 'unit' => 'semicircles'},
5901
29 => +{'name' => 'name'},
5902
30 => +{'name' => 'normalized_power', 'unit' => 'watts'},
5903
31 => +{'name' => 'left_right_balance', 'type_name' => 'left_right_balance_100'},
5904
32 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
5905
33 => +{'name' => 'total_work', 'unit' => 'J'},
5906
34 => +{'name' => 'avg_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5907
35 => +{'name' => 'max_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5908
36 => +{'name' => 'gps_accuracy', 'unit' => 'm'},
5909
37 => +{'name' => 'avg_grade', 'scale' => 100, 'unit' => '%'},
5910
38 => +{'name' => 'avg_pos_grade', 'scale' => 100, 'unit' => '%'},
5911
39 => +{'name' => 'avg_neg_grade', 'scale' => 100, 'unit' => '%'},
5912
40 => +{'name' => 'max_pos_grade', 'scale' => 100, 'unit' => '%'},
5913
41 => +{'name' => 'max_neg_grade', 'scale' => 100, 'unit' => '%'},
5914
42 => +{'name' => 'avg_temperature', 'unit' => 'deg.C'},
5915
43 => +{'name' => 'max_temperature', 'unit' => 'deg.C'},
5916
44 => +{'name' => 'total_moving_time', 'scale' => 1000, 'unit' => 's'},
5917
45 => +{'name' => 'avg_pos_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5918
46 => +{'name' => 'avg_neg_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5919
47 => +{'name' => 'max_pos_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5920
48 => +{'name' => 'max_neg_vertical_speed', 'scale' => 1000, 'unit' => 'm/s'},
5921
49 => +{'name' => 'time_in_hr_zone', 'scale' => 1000, 'unit' => 's'},
5922
50 => +{'name' => 'time_in_speed_zone', 'scale' => 1000, 'unit' => 's'},
5923
51 => +{'name' => 'time_in_cadence_zone', 'scale' => 1000, 'unit' => 's'},
5924
52 => +{'name' => 'time_in_power_zone', 'scale' => 1000, 'unit' => 's'},
5925
53 => +{'name' => 'repetition_num'},
5926
54 => +{'name' => 'min_altitude', 'scale' => 5, 'offset' => 500, 'unit' => 'm'},
5927
55 => +{'name' => 'min_heart_rate', 'unit' => 'bpm'},
5928
56 => +{'name' => 'active_time', 'scale' => 1000, 'unit' => 's'},
5929
57 => +{'name' => 'wkt_step_index', 'type_name' => 'message_index'},
5930
58 => +{'name' => 'sport_event', 'type_name' => 'sport_event'},
5931
59 => +{'name' => 'avg_left_torque_effectiveness', 'scale' => 2, 'unit' => '%'},
5932
60 => +{'name' => 'avg_right_torque_effectiveness', 'scale' => 2, 'unit' => '%'},
5933
61 => +{'name' => 'avg_left_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5934
62 => +{'name' => 'avg_right_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5935
63 => +{'name' => 'avg_combined_pedal_smoothness', 'scale' => 2, 'unit' => '%'},
5936
64 => +{'name' => 'status', 'type_name' => 'segment_lap_status'},
5937
65 => +{'name' => 'uuid'},
5938
66 => +{'name' => 'avg_fractional_cadence', 'scale' => 128, 'unit' => 'rpm'},
5939
67 => +{'name' => 'max_fractional_cadence', 'scale' => 128, 'unit' => 'rpm'},
5940
68 => +{'name' => 'total_fractional_cycles', 'scale' => 128, 'unit' => 'cycles'},
5941
69 => +{'name' => 'front_gear_shift_count'},
5942
70 => +{'name' => 'rear_gear_shift_count'},
5943
71 => +{'name' => 'time_standing', 'scale' => 1000, 'unit' => 's'},
5944
72 => +{'name' => 'stand_count'},
5945
73 => +{'name' => 'avg_left_pco', 'unit' => 'mm'},
5946
74 => +{'name' => 'avg_right_pco', 'unit' => 'mm'},
5947
75 => +{'name' => 'avg_left_power_phase', 'scale' => 0.7111111, 'unit' => 'degrees'},
5948
76 => +{'name' => 'avg_left_power_phase_peak', 'scale' => 0.7111111, 'unit' => 'degrees'},
5949
77 => +{'name' => 'avg_right_power_phase', 'scale' => 0.7111111, 'unit' => 'degrees'},
5950
78 => +{'name' => 'avg_right_power_phase_peak', 'scale' => 0.7111111, 'unit' => 'degrees'},
5951
79 => +{'name' => 'avg_power_position', 'unit' => 'watts'},
5952
80 => +{'name' => 'max_power_position', 'unit' => 'watts'},
5953
81 => +{'name' => 'avg_cadence_position', 'unit' => 'rpm'},
5954
82 => +{'name' => 'max_cadence_position', 'unit' => 'rpm'},
5955
83 => +{'name' => 'manufacturer', 'type_name' => 'manufacturer'},
5956
84 => +{'name' => 'total_grit', 'unit' => 'kGrit'},
5957
85 => +{'name' => 'total_flow', 'unit' => 'Flow'},
5958
86 => +{'name' => 'avg_grit', 'unit' => 'kGrit'},
5959
87 => +{'name' => 'avg_flow', 'unit' => 'Flow'},
5960
89 => +{'name' => 'total_fractional_ascent', 'unit' => 'm'},
5961
90 => +{'name' => 'total_fractional_descent', 'unit' => 'm'},
5962
91 => +{ 'name' => 'enhanced_avg_altitude', 'unit' => 'm', 'scale' => 5 },
5963
92 => +{ 'name' => 'enhanced_max_altitude', 'unit' => 'm', 'scale' => 5 },
5964
93 => +{ 'name' => 'enhanced_min_altitude', 'unit' => 'm', 'scale' => 5 },
5965
},
5966
5967
'segment_file' => +{ # begins === Segment list file messages === section
5968
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5969
1 => +{'name' => 'file_uuid'},
5970
3 => +{'name' => 'enabled', 'type_name' => 'bool'},
5971
4 => +{'name' => 'user_profile_primary_key'},
5972
7 => +{'name' => 'leader_type', 'type_name' => 'segment_leaderboard_type'},
5973
8 => +{'name' => 'leader_group_primary_key'},
5974
9 => +{'name' => 'leader_activity_id'},
5975
10 => +{'name' => 'leader_activity_id_string'},
5976
11 => +{'name' => 'default_race_leader'},
5977
},
5978
5979
'workout' => +{ # begins === Workout file messages === section
5980
4 => +{'name' => 'sport', 'type_name' => 'sport'},
5981
5 => +{'name' => 'capabilities', 'type_name' => 'workout_capabilities'},
5982
6 => +{'name' => 'num_valid_steps'},
5983
7 => +{'name' => 'protection'}, # not present?
5984
8 => +{'name' => 'wkt_name'},
5985
11 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
5986
14 => +{'name' => 'pool_length', 'scale' => 100, 'unit' => 'm'},
5987
15 => +{'name' => 'pool_length_unit', 'type_name' => 'display_measure'},
5988
},
5989
5990
'workout_session' => +{
5991
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
5992
0 => +{'name' => 'sport', 'type_name' => 'sport'},
5993
1 => +{'name' => 'sub_sport', 'type_name' => 'sub_sport'},
5994
2 => +{'name' => 'num_valid_steps'},
5995
3 => +{'name' => 'first_step_index'},
5996
4 => +{'name' => 'pool_length', 'scale' => 100, 'unit' => 'm'},
5997
5 => +{'name' => 'pool_length_unit', 'type_name' => 'display_measure'},
5998
},
5999
6000
'workout_step' => +{
6001
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6002
0 => +{'name' => 'wkt_step_name'},
6003
1 => +{'name' => 'duration_type', 'type_name' => 'wkt_step_duration'},
6004
6005
2 => +{
6006
'name' => 'duration_value',
6007
6008
'switch' => +{
6009
'_by' => 'duration_type',
6010
'time' => +{'name' => 'duration_time', 'scale' => 1000, 'unit' => 's'},
6011
'repetition_time' => +{'name' => 'duration_time', 'scale' => 1000, 'unit' => 's'},
6012
'distance' => +{'name' => 'duration_distance', 'scale' => 100, 'unit' => 'm'},
6013
'hr_less_than' => +{'name' => 'duration_hr', 'type_name' => 'workout_hr', 'unit' => 'bpm'},
6014
'hr_greater_than' => +{'name' => 'duration_hr', 'type_name' => 'workout_hr', 'unit' => 'bpm'},
6015
'calories' => +{'name' => 'duration_calories', 'unit' => 'kcal'},
6016
'repeat_until_steps_cmplt' => +{'name' => 'duration_step'},
6017
'repeat_until_time' => +{'name' => 'duration_step'},
6018
'repeat_until_distance' => +{'name' => 'duration_step'},
6019
'repeat_until_calories' => +{'name' => 'duration_step'},
6020
'repeat_until_hr_less_than' => +{'name' => 'duration_step'},
6021
'repeat_until_hr_greater_than' => +{'name' => 'duration_step'},
6022
'repeat_until_power_less_than' => +{'name' => 'duration_step'},
6023
'repeat_until_power_greater_than' => +{'name' => 'duration_step'},
6024
'power_less_than' => +{'name' => 'duration_power', 'type_name' => 'workout_power', 'unit' => 'watts'},
6025
'power_greater_than' => +{'name' => 'duration_power', 'type_name' => 'workout_power', 'unit' => 'watts'},
6026
'reps' => +{'name' => 'duration_reps'},
6027
},
6028
},
6029
6030
3 => +{'name' => 'target_type', 'type_name' => 'wkt_step_target'},
6031
6032
4 => +{
6033
'name' => 'target_value',
6034
6035
'switch' => +{
6036
'_by' => [qw(target_type duration_type)],
6037
'speed' => +{'name' => 'target_speed_zone'},
6038
'heart_rate' => +{'name' => 'target_hr_zone'},
6039
'cadence' => +{'name' => 'target_cadence_zone'},
6040
'power' => +{'name' => 'target_power_zone'},
6041
'repeat_until_steps_cmplt' => +{'name' => 'repeat_steps'},
6042
'repeat_until_time' => +{'name' => 'repeat_time', 'scale' => 1000, 'unit' => 's'},
6043
'repeat_until_distance' => +{'name' => 'repeat_distance', 'scale' => 100, 'unit' => 'm'},
6044
'repeat_until_calories' => +{'name' => 'repeat_calories', 'unit' => 'kcal'},
6045
'repeat_until_hr_less_than' => +{'name' => 'repeat_hr', 'type_name' => 'workout_hr', 'unit' => 'bpm'},
6046
'repeat_until_hr_greater_than' => +{'name' => 'repeat_hr', 'type_name' => 'workout_hr', 'unit' => 'bpm'},
6047
'repeat_until_power_less_than' => +{'name' => 'repeat_power', 'type_name' => 'workout_power', 'unit' => 'watts'},
6048
'repeat_until_power_greater_than' => +{'name' => 'repeat_power', 'type_name' => 'workout_power', 'unit' => 'watts'},
6049
'swim_stroke' => +{'name' => 'target_stroke_type', 'type_name' => 'swim_stroke'},
6050
},
6051
},
6052
6053
5 => +{
6054
'name' => 'custom_target_value_low',
6055
6056
'switch' => +{
6057
'_by' => 'target_type',
6058
'speed' => +{'name' => 'custom_target_speed_low', 'scale' => 1000, 'unit' => 'm/s'},
6059
'heart_rate' => +{'name' => 'custom_target_heart_rate_low', 'type_name' => 'workout_hr', 'unit' => 'bpm'},
6060
'cadence' => +{'name' => 'custom_target_cadence_low', 'unit' => 'rpm'},
6061
'power' => +{'name' => 'custom_target_power_low', 'type_name' => 'workout_power', 'unit' => 'watts'},
6062
},
6063
},
6064
6065
6 => +{
6066
'name' => 'custom_target_value_high',
6067
6068
'switch' => +{
6069
'_by' => 'target_type',
6070
'speed' => +{'name' => 'custom_target_speed_high', 'scale' => 1000, 'unit' => 'm/s'},
6071
'heart_rate' => +{'name' => 'custom_target_heart_rate_high', 'type_name' => 'workout_hr', 'unit' => 'bpm'},
6072
'cadence' => +{'name' => 'custom_target_cadence_high', 'unit' => 'rpm'},
6073
'power' => +{'name' => 'custom_target_power_high', 'type_name' => 'workout_power', 'unit' => 'watts'},
6074
},
6075
},
6076
6077
7 => +{'name' => 'intensity', 'type_name' => 'intensity'},
6078
8 => +{'name' => 'notes', 'type_name' => 'string'},
6079
9 => +{'name' => 'equipment', 'type_name' => 'workout_equipment'},
6080
10 => +{'name' => 'exercise_category', 'type_name' => 'exercise_category'},
6081
11 => +{'name' => 'exercise_name'},
6082
12 => +{'name' => 'exercise_weight', 'scale' => 100, 'unit' => 'kg'},
6083
13 => +{'name' => 'weight_display_unit', 'type_name' => 'fit_base_unit'},
6084
19 => +{'name' => 'secondary_target_type', 'type_name' => 'wkt_step_target'},
6085
20 => +{
6086
'name' => 'secondary_target_value',
6087
'switch' => +{
6088
'_by' => 'secondary_target_type',
6089
'speed' => +{'name' => 'secondary_target_speed_zone'},
6090
'heart_rate' => +{'name' => 'secondary_target_hr_zone'},
6091
'cadence' => +{'name' => 'secondary_target_cadence_zone'},
6092
'power' => +{'name' => 'secondary_target_power_zone'},
6093
'swim_stroke' => +{'name' => 'secondary_target_stroke_type', 'type_name' => 'swim_stroke'},
6094
},
6095
},
6096
},
6097
6098
'exercise_title' => +{
6099
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6100
0 => +{'name' => 'exercise_category', 'type_name' => 'exercise_category'},
6101
1 => +{'name' => 'exercise_name'},
6102
2 => +{'name' => 'wkt_step_name', 'type_name' => 'string'},
6103
},
6104
6105
'schedule' => +{ # begins === Schedule file messages === section
6106
0 => +{'name' => 'manufacturer', 'type_name' => 'manufacturer'},
6107
6108
1 => +{
6109
'name' => 'product',
6110
6111
'switch' => +{
6112
'_by' => 'manufacturer',
6113
'garmin' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
6114
'dynastream' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
6115
'dynastream_oem' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
6116
'favero_electronics' => +{'name' => 'favero_product', 'type_name' => 'favero_product'},
6117
'tacx' => +{'name' => 'garmin_product', 'type_name' => 'garmin_product'},
6118
},
6119
},
6120
6121
2 => +{'name' => 'serial_number'},
6122
3 => +{'name' => 'time_created', 'type_name' => 'date_time'},
6123
4 => +{'name' => 'completed', 'type_name' => 'bool'},
6124
5 => +{'name' => 'type', 'type_name' => 'schedule'},
6125
6 => +{'name' => 'schedule_time', 'type_name' => 'local_date_time'},
6126
},
6127
6128
'totals' => +{ # begins === Totals file messages === section
6129
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6130
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6131
0 => +{'name' => 'timer_time', 'unit' => 's'},
6132
1 => +{'name' => 'distance', 'unit' => 'm'},
6133
2 => +{'name' => 'calories', 'unit' => 'kcal'},
6134
3 => +{'name' => 'sport', 'type_name' => 'sport'},
6135
4 => +{'name' => 'elapsed_time', 'unit' => 's'},
6136
5 => +{'name' => 'sessions'},
6137
6 => +{'name' => 'active_time', 'unit' => 's'},
6138
9 => +{'name' => 'sport_index'},
6139
10 => +{'name' => 'profile_name'}, # unknown STRING
6140
},
6141
6142
'weight_scale' => +{ # begins === Weight scale file messages === section
6143
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6144
0 => +{'name' => 'weight', 'type_name' => 'weight', 'scale' => 100, 'unit' => 'kg'},
6145
1 => +{'name' => 'percent_fat', 'scale' => 100, 'unit' => '%'},
6146
2 => +{'name' => 'percent_hydration', 'scale' => 100, 'unit' => '%'},
6147
3 => +{'name' => 'visceral_fat_mass', 'scale' => 100, 'unit' => 'kg'},
6148
4 => +{'name' => 'bone_mass', 'scale' => 100, 'unit' => 'kg'},
6149
5 => +{'name' => 'muscle_mass', 'scale' => 100, 'unit' => 'kg'},
6150
7 => +{'name' => 'basal_met', 'scale' => 4, 'unit' => 'kcal/day'},
6151
8 => +{'name' => 'physique_rating'},
6152
9 => +{'name' => 'active_met', 'scale' => 4, 'unit' => 'kcal/day'},
6153
10 => +{'name' => 'metabolic_age', 'unit' => 'years'},
6154
11 => +{'name' => 'visceral_fat_rating'},
6155
12 => +{'name' => 'user_profile_index', 'type_name' => 'message_index'},
6156
},
6157
6158
'blood_pressure' => +{ # begins === Blood pressure file messages === section
6159
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6160
0 => +{'name' => 'systolic_pressure', 'unit' => 'mmHg'},
6161
1 => +{'name' => 'diastolic_pressure', 'unit' => 'mmHg'},
6162
2 => +{'name' => 'mean_arterial_pressure', 'unit' => 'mmHg'},
6163
3 => +{'name' => 'map_3_sample_mean', 'unit' => 'mmHg'},
6164
4 => +{'name' => 'map_morning_values', 'unit' => 'mmHg'},
6165
5 => +{'name' => 'map_evening_values', 'unit' => 'mmHg'},
6166
6 => +{'name' => 'heart_rate', 'unit' => 'bpm'},
6167
7 => +{'name' => 'heart_rate_type', 'type_name' => 'hr_type'},
6168
8 => +{'name' => 'status', 'type_name' => 'bp_status'},
6169
9 => +{'name' => 'user_profile_index', 'type_name' => 'message_index'},
6170
},
6171
6172
'monitoring_info' => +{ # begins === Monitoring file messages === section
6173
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6174
0 => +{'name' => 'local_timestamp', 'type_name' => 'local_date_time'},
6175
1 => +{'name' => 'activity_type', 'type_name' => 'activity_type'},
6176
3 => +{'name' => 'cycles_to_distance', 'scale' => 5000, 'unit' => 'm/cycle'},
6177
4 => +{'name' => 'cycles_to_calories', 'scale' => 5000, 'unit' => 'kcal/cycle'},
6178
5 => +{'name' => 'resting_metabolic_rate', 'unit' => 'kcal/day'},
6179
},
6180
6181
'monitoring' => +{
6182
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6183
0 => +{'name' => 'device_index', 'type_name' => 'device_index'},
6184
1 => +{'name' => 'calories', 'unit' => 'kcal'},
6185
2 => +{'name' => 'distance', 'scale' => 100, 'unit' => 'm'},
6186
6187
3 => +{
6188
'name' => 'cycles', 'scale' => 2, 'unit' => 'cycles',
6189
6190
'switch' => +{
6191
'_by' => 'activity_type',
6192
'walking' => +{'name' => 'total_steps', 'scale' => 1, 'unit' => 'steps'},
6193
'running' => +{'name' => 'total_strides', 'scale' => 1, 'unit' => 'strides'},
6194
'cycling' => +{'name' => 'total_strokes', 'scale' => 2, 'unit' => 'strokes'},
6195
'swimming' => +{'name' => 'total_strokes', 'scale' => 2, 'unit' => 'strokes'},
6196
},
6197
},
6198
6199
4 => +{'name' => 'active_time', 'scale' => 1000, 'unit' => 's'},
6200
5 => +{'name' => 'activity_type', 'type_name' => 'activity_type'},
6201
6 => +{'name' => 'activity_subtype', 'type_name' => 'activity_subtype'},
6202
7 => +{'name' => 'activity_level', 'type_name' => 'activity_level'},
6203
8 => +{'name' => 'distance_16', 'scale' => 100, 'unit' => 'm'},
6204
9 => +{'name' => 'cycles_16', 'scale' => 2, 'unit' => 'cycles'},
6205
10 => +{'name' => 'active_time_16', 'unit' => 's'},
6206
11 => +{'name' => 'local_timestamp', 'type_name' => 'local_date_time'},
6207
12 => +{'name' => 'temperature', 'scale' => 100, 'unit' => 'deg.C'},
6208
14 => +{'name' => 'temperature_min', 'scale' => 100, 'unit' => 'deg.C'},
6209
15 => +{'name' => 'temperature_max', 'scale' => 100, 'unit' => 'deg.C'},
6210
16 => +{'name' => 'activity_time', 'unit' => 'min'},
6211
19 => +{'name' => 'active_calories', 'unit' => 'kcal'},
6212
24 => +{'name' => 'current_activity_type_intensity'}, # complex decoding!
6213
25 => +{'name' => 'timestamp_min_8', 'unit' => 'min'},
6214
26 => +{'name' => 'timestamp_16', 'unit' => 's'},
6215
27 => +{'name' => 'heart_rate', 'unit' => 'bpm'},
6216
28 => +{'name' => 'intensity', 'scale' => 10},
6217
29 => +{'name' => 'duration_min', 'unit' => 'min'},
6218
30 => +{'name' => 'duration', 'unit' => 's'},
6219
31 => +{'name' => 'ascent', 'scale' => 1000, 'unit' => 'm'},
6220
32 => +{'name' => 'descent', 'scale' => 1000, 'unit' => 'm'},
6221
33 => +{'name' => 'moderate_activity_minutes', 'unit' => 'min'},
6222
34 => +{'name' => 'vigorous_activity_minutes', 'unit' => 'min'},
6223
},
6224
6225
'hr' => +{
6226
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6227
0 => +{'name' => 'fractional_timestamp', 'scale' => 32768, 'unit' => 's'},
6228
1 => +{'name' => 'time256', 'scale' => 256, 'unit' => 's'},
6229
6 => +{'name' => 'filtered_bpm', 'unit' => 'bpm'},
6230
9 => +{'name' => 'event_timestamp', 'scale' => 1024, 'unit' => 's'},
6231
10 => +{'name' => 'event_timestamp_12', 'scale' => 1024, 'unit' => 's'},
6232
},
6233
6234
'stress_level' => +{
6235
0 => +{'name' => 'stress_level_value'},
6236
1 => +{'name' => 'stress_level_time', 'type_name' => 'date_time', 'unit' => 's'},
6237
},
6238
6239
'memo_glob' => +{ # begins === Other messages === section
6240
250 => +{'name' => 'part_index'},
6241
0 => +{'name' => 'memo'},
6242
1 => +{'name' => 'message_number'},
6243
2 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6244
},
6245
6246
'ant_channel_id' => +{
6247
0 => +{'name' => 'channel_number'},
6248
1 => +{'name' => 'device_type'},
6249
2 => +{'name' => 'device_number'},
6250
3 => +{'name' => 'transmission_type'},
6251
4 => +{'name' => 'device_index', 'type_name' => 'device_index'},
6252
},
6253
6254
'ant_rx' => +{
6255
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6256
0 => +{'name' => 'fractional_timestamp', 'scale' => 32768, 'unit' => 's'},
6257
1 => +{'name' => 'mesg_id'},
6258
2 => +{'name' => 'mesg_data'},
6259
3 => +{'name' => 'channel_number'},
6260
4 => +{'name' => 'data'},
6261
},
6262
6263
'ant_tx' => +{
6264
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6265
0 => +{'name' => 'fractional_timestamp', 'scale' => 32768, 'unit' => 's'},
6266
1 => +{'name' => 'mesg_id'},
6267
2 => +{'name' => 'mesg_data'},
6268
3 => +{'name' => 'channel_number'},
6269
4 => +{'name' => 'data'},
6270
},
6271
6272
'exd_screen_configuration' => +{
6273
0 => +{'name' => 'screen_index'},
6274
1 => +{'name' => 'field_count'},
6275
2 => +{'name' => 'layout', 'type_name' => 'exd_layout'},
6276
3 => +{'name' => 'screen_enabled', 'type_name' => 'bool'},
6277
},
6278
6279
'exd_data_field_configuration' => +{
6280
0 => +{'name' => 'screen_index'},
6281
1 => +{'name' => 'concept_field'}, # complex decoding!
6282
2 => +{'name' => 'field_id'},
6283
3 => +{'name' => 'concept_count'},
6284
4 => +{'name' => 'display_type', 'type_name' => 'exd_display_type'},
6285
5 => +{'name' => 'title'},
6286
},
6287
6288
'exd_data_concept_configuration' => +{
6289
0 => +{'name' => 'screen_index'},
6290
1 => +{'name' => 'concept_field'}, # complex decoding!
6291
2 => +{'name' => 'field_id'},
6292
3 => +{'name' => 'concept_index'},
6293
4 => +{'name' => 'data_page'},
6294
5 => +{'name' => 'concept_key'},
6295
6 => +{'name' => 'scaling'},
6296
7 => +{'name' => 'unknown7'}, # unknown UINT8
6297
8 => +{'name' => 'data_units', 'type_name' => 'exd_data_units'},
6298
9 => +{'name' => 'qualifier', 'type_name' => 'exd_qualifiers'},
6299
10 => +{'name' => 'descriptor', 'type_name' => 'exd_descriptors'},
6300
11 => +{'name' => 'is_signed', 'type_name' => 'bool'},
6301
},
6302
6303
'dive_summary' => +{
6304
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6305
0 => +{'name' => 'reference_mesg', 'type_name' => 'mesg_num'},
6306
1 => +{'name' => 'reference_index', 'type_name' => 'message_index'},
6307
2 => +{'name' => 'avg_depth', 'scale' => 1000, 'unit' => 'm'},
6308
3 => +{'name' => 'max_depth', 'scale' => 1000, 'unit' => 'm'},
6309
4 => +{'name' => 'surface_interval', 'unit' => 's'},
6310
5 => +{'name' => 'start_cns', 'unit' => '%'},
6311
6 => +{'name' => 'end_cns', 'unit' => '%'},
6312
7 => +{'name' => 'start_n2', 'unit' => '%'},
6313
8 => +{'name' => 'end_n2', 'unit' => '%'},
6314
9 => +{'name' => 'o2_toxicity'},
6315
10 => +{'name' => 'dive_number'},
6316
11 => +{'name' => 'bottom_time', 'scale' => 1000, 'unit' => 's'},
6317
12 => +{ 'name' => 'avg_pressure_sac', 'unit' => 'bar/min', 'scale' => 100 },# Average pressure-based surface air consumption
6318
13 => +{ 'name' => 'avg_volume_sac', 'unit' => 'l/min', 'scale' => 100 }, # Average volumetric surface air consumption
6319
14 => +{ 'name' => 'avg_rmv', 'unit' => 'l/min', 'scale' => 100 }, # Average respiratory minute volume
6320
15 => +{ 'name' => 'descent_time', 'unit' => 's', 'scale' => 1000 }, # Time to reach deepest level stop
6321
16 => +{ 'name' => 'ascent_time', 'unit' => 's', 'scale' => 1000 }, # Time after leaving bottom until reaching surface
6322
17 => +{ 'name' => 'avg_ascent_rate', 'unit' => 'm/s', 'scale' => 1000 }, # Average ascent rate, not including descents or stops
6323
22 => +{ 'name' => 'avg_descent_rate', 'unit' => 'm/s', 'scale' => 1000 }, # Average descent rate, not including ascents or stops
6324
23 => +{ 'name' => 'max_ascent_rate', 'unit' => 'm/s', 'scale' => 1000 }, # Maximum ascent rate
6325
24 => +{ 'name' => 'max_descent_rate', 'unit' => 'm/s', 'scale' => 1000 }, # Maximum descent rate
6326
25 => +{ 'name' => 'hang_time', 'unit' => 's', 'scale' => 1000 }, # Time spent neither ascending nor descending
6327
},
6328
6329
'hrv' => +{ # heart rate variability
6330
0 => +{'name' => 'time', 'scale' => 1000, 'unit' => 's'},
6331
},
6332
6333
'tank_update' => +{
6334
253 => +{ 'name' => 'timestamp', 'type_name' => 'date_time' },
6335
0 => +{ 'name' => 'sensor', 'type_name' => 'ant_channel_id' },
6336
1 => +{ 'name' => 'pressure', 'unit' => 'bar', 'scale' => 100 },
6337
},
6338
6339
'tank_summary' => +{
6340
253 => +{ 'name' => 'timestamp', 'type_name' => 'date_time' },
6341
0 => +{ 'name' => 'sensor', 'type_name' => 'ant_channel_id' },
6342
1 => +{ 'name' => 'start_pressure', 'unit' => 'bar', 'scale' => 100 },
6343
2 => +{ 'name' => 'end_pressure', 'unit' => 'bar', 'scale' => 100 },
6344
3 => +{ 'name' => 'volume_used', 'unit' => 'l', 'scale' => 100 },
6345
},
6346
6347
'pad' => +{
6348
0 => +{'name' => 'pad'},
6349
},
6350
6351
'source' => +{ # begins === Undocumented messages === section
6352
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6353
# device_index in device_info
6354
0 => +{'name' => 'unknown0', 'type_name' => 'device_index'}, # unknown UINT8
6355
1 => +{'name' => 'unknown1', 'type_name' => 'device_index'}, # unknown UINT8
6356
2 => +{'name' => 'unknown2', 'type_name' => 'device_index'}, # unknown UINT8
6357
3 => +{'name' => 'unknown3', 'type_name' => 'device_index'}, # unknown UINT8
6358
4 => +{'name' => 'unknown4', 'type_name' => 'device_index'}, # unknown UINT8
6359
5 => +{'name' => 'unknown5'}, # unknown ENUM
6360
6 => +{'name' => 'unknown6'}, # unknown UINT8
6361
7 => +{'name' => 'unknown7'}, # unknown UINT8
6362
8 => +{'name' => 'unknown8'}, # unknown UINT8
6363
9 => +{'name' => 'unknown9'}, # unknown UINT8
6364
},
6365
6366
'location' => +{
6367
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6368
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6369
0 => +{'name' => 'name'}, # unknown STRING
6370
1 => +{'name' => 'position_lat', 'unit' => 'semicircles'}, # unknown SINT32
6371
2 => +{'name' => 'position_long', 'unit' => 'semicircles'}, # unknown SINT32
6372
3 => +{'name' => 'unknown3'}, # unknown UINT16 (elevation?)
6373
4 => +{'name' => 'unknown4'}, # unknown UINT16
6374
5 => +{'name' => 'unknown5'}, # unknown UINT16
6375
6 => +{'name' => 'unknown6'}, # unknown STRING
6376
},
6377
6378
'battery' => +{
6379
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6380
0 => +{'name' => 'unknown0'}, # unknown UINT16 (voltage with scale?)
6381
1 => +{'name' => 'unknown1'}, # unknown SINT16
6382
2 => +{'name' => 'charge_level', 'unit' => '%'}, # unknown UINT8
6383
3 => +{'name' => 'temperature', 'unit' => 'deg.C'}, # unknown SINT8
6384
},
6385
6386
'sensor' => +{
6387
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6388
0 => +{'name' => 'unknown0'}, # unknown UINT32Z
6389
1 => +{'name' => 'unknown1'}, # unknown UINT8
6390
2 => +{'name' => 'sensor_id'}, # unknown STRING
6391
3 => +{'name' => 'unknown3'}, # unknown ENUM
6392
4 => +{'name' => 'unknown4'}, # unknown ENUM
6393
5 => +{'name' => 'unknown5'}, # unknown ENUM
6394
6 => +{'name' => 'unknown6'}, # unknown ENUM
6395
7 => +{'name' => 'unknown7'}, # unknown ENUM
6396
8 => +{'name' => 'unknown8'}, # unknown ENUM
6397
9 => +{'name' => 'unknown9'}, # unknown UINT8
6398
10 => +{'name' => 'wheel_size', 'unit' => 'mm'}, # unknown UINT16
6399
11 => +{'name' => 'unknown11'}, # unknown UINT16
6400
12 => +{'name' => 'unknown12'}, # unknown UINT8
6401
13 => +{'name' => 'unknown13'}, # unknown UINT32
6402
14 => +{'name' => 'unknown14'}, # unknown UINT8
6403
15 => +{'name' => 'unknown15'}, # unknown UINT8
6404
16 => +{'name' => 'unknown16'}, # unknown UINT8
6405
17 => +{'name' => 'unknown17'}, # unknown UINT8Z
6406
18 => +{'name' => 'unknown18'}, # unknown UINT8Z (array[4])
6407
19 => +{'name' => 'unknown19'}, # unknown UINT8Z
6408
20 => +{'name' => 'unknown20'}, # unknown UINT8Z (array[12])
6409
21 => +{'name' => 'unknown21'}, # unknown UINT16
6410
25 => +{'name' => 'unknown25'}, # unknown UINT16
6411
26 => +{'name' => 'unknown26'}, # unknown UINT16
6412
27 => +{'name' => 'unknown27'}, # unknown UINT8
6413
28 => +{'name' => 'unknown28'}, # unknown UINT8 (array[4])
6414
29 => +{'name' => 'unknown29'}, # unknown UINT8 (array[4])
6415
30 => +{'name' => 'unknown30'}, # unknown UINT8 (array[4])
6416
31 => +{'name' => 'unknown31'}, # unknown UINT8
6417
32 => +{'name' => 'unknown32'}, # unknown UINT16
6418
33 => +{'name' => 'unknown33'}, # unknown UINT16
6419
34 => +{'name' => 'unknown34'}, # unknown UINT16
6420
35 => +{'name' => 'unknown35'}, # unknown UINT16
6421
36 => +{'name' => 'unknown36'}, # unknown ENUM
6422
37 => +{'name' => 'unknown37'}, # unknown ENUM (array[7])
6423
38 => +{'name' => 'unknown38'}, # unknown ENUM (array[7])
6424
39 => +{'name' => 'unknown39'}, # unknown ENUM (array[7])
6425
40 => +{'name' => 'unknown40'}, # unknown UINT16Z
6426
41 => +{'name' => 'unknown41'}, # unknown UINT8 (array[7])
6427
42 => +{'name' => 'unknown42'}, # unknown ENUM
6428
43 => +{'name' => 'unknown43'}, # unknown ENUM
6429
44 => +{'name' => 'unknown44'}, # unknown UINT8Z
6430
47 => +{'name' => 'unknown47'}, # unknown ENUM
6431
48 => +{'name' => 'unknown48'}, # unknown ENUM
6432
},
6433
6434
);
6435
6436
my %msgtype_by_num = (
6437
13 => +{ # begins === Unknown messages === section
6438
'_number' => 13,
6439
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6440
1 => +{'name' => 'unknown1'}, # unknown ENUM
6441
2 => +{'name' => 'unknown2'}, # unknown UINT16
6442
3 => +{'name' => 'unknown3'}, # unknown ENUM
6443
4 => +{'name' => 'unknown4'}, # unknown UINT32
6444
5 => +{'name' => 'unknown5'}, # unknown SINT32
6445
6 => +{'name' => 'unknown6'}, # unknown SINT32
6446
7 => +{'name' => 'unknown7'}, # unknown ENUM
6447
8 => +{'name' => 'unknown8'}, # unknown UINT16
6448
9 => +{'name' => 'unknown9'}, # unknown ENUM
6449
10 => +{'name' => 'unknown10'}, # unknown UINT16
6450
11 => +{'name' => 'unknown11'}, # unknown UINT8
6451
12 => +{'name' => 'unknown12'}, # unknown ENUM
6452
13 => +{'name' => 'unknown13'}, # unknown ENUM
6453
14 => +{'name' => 'unknown14'}, # unknown ENUM
6454
15 => +{'name' => 'unknown15'}, # unknown ENUM
6455
16 => +{'name' => 'unknown16'}, # unknown ENUM
6456
17 => +{'name' => 'unknown17'}, # unknown ENUM
6457
18 => +{'name' => 'unknown18'}, # unknown ENUM
6458
19 => +{'name' => 'unknown19'}, # unknown UINT16
6459
25 => +{'name' => 'unknown25'}, # unknown ENUM
6460
27 => +{'name' => 'unknown27'}, # unknown ENUM
6461
30 => +{'name' => 'unknown30'}, # unknown ENUM
6462
31 => +{'name' => 'unknown31'}, # unknown UINT32
6463
32 => +{'name' => 'unknown32'}, # unknown UINT16
6464
33 => +{'name' => 'unknown33'}, # unknown UINT32
6465
34 => +{'name' => 'unknown34'}, # unknown ENUM
6466
50 => +{'name' => 'unknown50'}, # unknown ENUM
6467
51 => +{'name' => 'unknown51'}, # unknown ENUM
6468
52 => +{'name' => 'unknown52'}, # unknown UINT16
6469
53 => +{'name' => 'unknown53'}, # unknown ENUM
6470
56 => +{'name' => 'unknown56'}, # unknown ENUM
6471
},
6472
6473
14 => +{
6474
'_number' => 14,
6475
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6476
1 => +{'name' => 'unknown1'}, # unknown ENUM
6477
3 => +{'name' => 'unknown3'}, # unknown UINT8
6478
4 => +{'name' => 'unknown4'}, # unknown UINT8 (array[10])
6479
5 => +{'name' => 'unknown5'}, # unknown ENUM (array[10])
6480
6 => +{'name' => 'unknown6'}, # unknown STRING
6481
7 => +{'name' => 'unknown7'}, # unknown UINT16 (array[10])
6482
},
6483
6484
16 => +{
6485
'_number' => 16,
6486
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6487
1 => +{'name' => 'unknown1'}, # unknown ENUM
6488
2 => +{'name' => 'unknown2'}, # unknown UINT32
6489
3 => +{'name' => 'unknown3'}, # unknown ENUM
6490
},
6491
6492
17 => +{
6493
'_number' => 17,
6494
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6495
1 => +{'name' => 'unknown1'}, # unknown ENUM
6496
2 => +{'name' => 'unknown2'}, # unknown ENUM
6497
3 => +{'name' => 'unknown3'}, # unknown UINT16
6498
4 => +{'name' => 'unknown4'}, # unknown ENUM
6499
5 => +{'name' => 'unknown5'}, # unknown UINT16
6500
},
6501
6502
70 => +{
6503
'_number' => 70,
6504
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6505
0 => +{'name' => 'unknown0'}, # unknown ENUM
6506
1 => +{'name' => 'unknown1'}, # unknown ENUM
6507
2 => +{'name' => 'unknown2'}, # unknown ENUM
6508
3 => +{'name' => 'unknown3'}, # unknown ENUM
6509
4 => +{'name' => 'unknown4'}, # unknown ENUM
6510
5 => +{'name' => 'unknown5'}, # unknown ENUM
6511
6 => +{'name' => 'unknown6'}, # unknown ENUM
6512
7 => +{'name' => 'unknown7'}, # unknown ENUM
6513
8 => +{'name' => 'unknown8'}, # unknown ENUM
6514
9 => +{'name' => 'unknown9'}, # unknown ENUM
6515
10 => +{'name' => 'unknown10'}, # unknown ENUM
6516
11 => +{'name' => 'unknown11'}, # unknown ENUM
6517
12 => +{'name' => 'unknown12'}, # unknown ENUM
6518
13 => +{'name' => 'unknown13'}, # unknown ENUM
6519
14 => +{'name' => 'unknown14'}, # unknown ENUM
6520
15 => +{'name' => 'unknown15'}, # unknown ENUM
6521
},
6522
6523
71 => +{
6524
'_number' => 71,
6525
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6526
0 => +{'name' => 'unknown0'}, # unknown ENUM
6527
1 => +{'name' => 'unknown1'}, # unknown ENUM
6528
2 => +{'name' => 'unknown2'}, # unknown ENUM
6529
3 => +{'name' => 'unknown3'}, # unknown UINT16
6530
4 => +{'name' => 'unknown4'}, # unknown ENUM
6531
},
6532
6533
79 => +{
6534
'_number' => 79,
6535
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6536
0 => +{'name' => 'unknown0'}, # unknown UINT16
6537
1 => +{'name' => 'unknown1'}, # unknown UINT8
6538
2 => +{'name' => 'unknown2'}, # unknown UINT8
6539
3 => +{'name' => 'unknown3'}, # unknown UINT16
6540
4 => +{'name' => 'unknown4'}, # unknown ENUM
6541
5 => +{'name' => 'unknown5'}, # unknown ENUM
6542
6 => +{'name' => 'unknown6'}, # unknown UINT8
6543
7 => +{'name' => 'unknown7'}, # unknown SINT8
6544
8 => +{'name' => 'unknown8'}, # unknown UINT16
6545
9 => +{'name' => 'unknown9'}, # unknown UINT16
6546
10 => +{'name' => 'unknown10'}, # unknown UINT8
6547
11 => +{'name' => 'unknown11'}, # unknown UINT16
6548
12 => +{'name' => 'unknown12'}, # unknown UINT16
6549
13 => +{'name' => 'unknown13'}, # unknown UINT16
6550
14 => +{'name' => 'unknown14'}, # unknown UINT8
6551
},
6552
6553
113 => +{
6554
'_number' => 113,
6555
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6556
0 => +{'name' => 'unknown0'}, # unknown UINT16
6557
1 => +{'name' => 'unknown1'}, # unknown ENUM
6558
2 => +{'name' => 'unknown2'}, # unknown UINT32
6559
3 => +{'name' => 'unknown3'}, # unknown UINT32
6560
4 => +{'name' => 'unknown4'}, # unknown UINT32
6561
5 => +{'name' => 'unknown5'}, # unknown ENUM
6562
},
6563
6564
114 => +{
6565
'_number' => 114,
6566
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6567
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6568
0 => +{'name' => 'unknown0'}, # unknown UINT16
6569
1 => +{'name' => 'unknown1'}, # unknown ENUM
6570
2 => +{'name' => 'unknown2'}, # unknown UINT32
6571
3 => +{'name' => 'unknown3'}, # unknown UINT32
6572
4 => +{'name' => 'unknown4'}, # unknown UINT32
6573
5 => +{'name' => 'unknown5'}, # unknown UINT32
6574
6 => +{'name' => 'unknown6'}, # unknown UINT32Z
6575
7 => +{'name' => 'unknown7'}, # unknown UINT32
6576
},
6577
6578
139 => +{
6579
'_number' => 139,
6580
254 => +{'name' => 'message_index', 'type_name' => 'message_index'},
6581
0 => +{'name' => 'unknown0'}, # unknown ENUM
6582
1 => +{'name' => 'unknown1'}, # unknown UINT16Z
6583
3 => +{'name' => 'unknown3'}, # unknown UINT8Z
6584
4 => +{'name' => 'unknown4'}, # unknown ENUM
6585
5 => +{'name' => 'unknown5'}, # unknown UINT16
6586
},
6587
6588
140 => +{
6589
'_number' => 140,
6590
253 => +{'name' => 'timestamp', 'type_name' => 'date_time'},
6591
0 => +{'name' => 'unknown0'}, # unknown UINT8
6592
1 => +{'name' => 'unknown1'}, # unknown UINT8
6593
2 => +{'name' => 'unknown2'}, # unknown SINT32
6594
3 => +{'name' => 'unknown3'}, # unknown SINT32
6595
4 => +{'name' => 'unknown4'}, # unknown UINT8
6596
5 => +{'name' => 'unknown5'}, # unknown SINT32
6597
6 => +{'name' => 'unknown6'}, # unknown SINT32
6598
7 => +{'name' => 'unknown7'}, # unknown SINT32
6599
8 => +{'name' => 'unknown8'}, # unknown UINT8
6600
9 => +{'name' => 'unknown9'}, # unknown UINT16
6601
10 => +{'name' => 'unknown10'}, # unknown UINT16
6602
11 => +{'name' => 'unknown11'}, # unknown ENUM
6603
12 => +{'name' => 'unknown12'}, # unknown ENUM
6604
13 => +{'name' => 'unknown13'}, # unknown UINT8
6605
14 => +{'name' => 'unknown14'}, # unknown UINT16
6606
15 => +{'name' => 'unknown15'}, # unknown UINT16
6607
16 => +{'name' => 'unknown16'}, # unknown UINT16
6608
17 => +{'name' => 'unknown17'}, # unknown SINT8
6609
18 => +{'name' => 'unknown18'}, # unknown UINT8
6610
19 => +{'name' => 'unknown19'}, # unknown UINT8
6611
},
6612
6613
203 => +{
6614
'_number' => 203,
6615
0 => +{'name' => 'unknown0'}, # unknown ENUM
6616
1 => +{'name' => 'unknown1'}, # unknown ENUM
6617
2 => +{'name' => 'unknown2'}, # unknown ENUM
6618
},
6619
6620
);
6621
6622
my $mesg_name_vs_num = $named_type{mesg_num};
6623
6624
for my $msgname (keys %msgtype_by_name) {
6625
my $msgtype = $msgtype_by_name{$msgname};
6626
6627
$msgtype->{_name} = $msgname;
6628
$msgtype->{_number} = $mesg_name_vs_num->{$msgname};
6629
$msgtype_by_num{$msgtype->{_number}} = $msgtype;
6630
6631
for my $fldnum (grep {/^\d+$/} keys %$msgtype) {
6632
my $flddesc = $msgtype->{$fldnum};
6633
6634
$flddesc->{number} = $fldnum;
6635
$msgtype->{$flddesc->{name}} = $flddesc;
6636
}
6637
}
6638
6639
=head2 Constructor Methods (class)
6640
6641
=over 4
6642
6643
=item new()
6644
6645
creates a new object and returns it.
6646
6647
=back
6648
6649
=cut
6650
6651
sub new {
6652
3
3
1
254
my $class = shift;
6653
3
9
my $self = +{};
6654
3
9
bless $self, $class;
6655
3
16
$self->initialize(@_);
6656
}
6657
6658
=head2 Class methods
6659
6660
=over 4
6661
6662
=item message_name(I)
6663
6664
returns the message name for I or undef.
6665
6666
=item message_number(I)
6667
6668
returns the message number for I or undef.
6669
6670
=back
6671
6672
=cut
6673
6674
sub message_name {
6675
0
0
1
0
my ($self, $mspec) = @_;
6676
0
0
0
my $msgtype = $mspec =~ /^\d+$/ ? $msgtype_by_num{$mspec} : $msgtype_by_name{$mspec};
6677
6678
0
0
0
if (ref $msgtype eq 'HASH') {
6679
0
0
$msgtype->{_name};
6680
} else {
6681
0
0
undef;
6682
}
6683
}
6684
6685
sub message_number {
6686
0
0
1
0
my ($self, $mspec) = @_;
6687
0
0
0
my $msgtype = $mspec =~ /^\d+$/ ? $msgtype_by_num{$mspec} : $msgtype_by_name{$mspec};
6688
6689
0
0
0
if (ref $msgtype eq 'HASH') {
6690
0
0
$msgtype->{_number};
6691
} else {
6692
0
0
undef;
6693
}
6694
}
6695
6696
=over 4
6697
6698
=item field_name(I, I)
6699
6700
returns the field name for I in I or undef.
6701
6702
=item field_number(I, I)
6703
6704
returns the field index for I in I or undef.
6705
6706
=back
6707
6708
=cut
6709
6710
sub field_name {
6711
0
0
1
0
my ($self, $mspec, $fspec) = @_;
6712
0
0
0
my $msgtype = $mspec =~ /^\d+$/ ? $msgtype_by_num{$mspec} : $msgtype_by_name{$mspec};
6713
6714
0
0
0
if (ref $msgtype eq 'HASH') {
6715
0
0
my $flddesc = $msgtype->{$fspec};
6716
ref $flddesc eq 'HASH'
6717
0
0
0
and return $flddesc->{name};
6718
}
6719
0
0
undef;
6720
}
6721
6722
sub field_number {
6723
0
0
1
0
my ($self, $mspec, $fspec) = @_;
6724
0
0
0
my $msgtype = $mspec =~ /^\d+$/ ? $msgtype_by_num{$mspec} : $msgtype_by_name{$mspec};
6725
6726
0
0
0
if (ref $msgtype eq 'HASH') {
6727
0
0
my $flddesc = $msgtype->{$fspec};
6728
ref $flddesc eq 'HASH'
6729
0
0
0
and return $flddesc->{number};
6730
}
6731
0
0
undef;
6732
}
6733
6734
=over 4
6735
6736
=item protocol_version_string()
6737
6738
returns a string representing the .FIT protocol version on which this class based.
6739
6740
=item profile_version_string()
6741
6742
returns a string representing the .FIT protocol version on which this class based.
6743
6744
=back
6745
6746
=cut
6747
6748
my $profile_current = '21.107';
6749
my $protocol_current = '2.3'; # is there such a thing as current protocol?
6750
6751
my $protocol_version_major_shift = 4;
6752
my $protocol_version_minor_mask = (1 << $protocol_version_major_shift) - 1;
6753
my $protocol_version_header_crc_started = _protocol_version_from_string("1.0");
6754
my $profile_version_scale = 100;
6755
6756
sub _protocol_version_from_string {
6757
6
6
13
my $s = shift;
6758
6
38
my ($major, $minor) = split /\./, $s, 2;
6759
6
50
25
return ($major + 0, $minor & $protocol_version_minor_mask) if wantarray;
6760
6
24
return ($major << $protocol_version_major_shift) | ($minor & $protocol_version_minor_mask)
6761
}
6762
6763
sub protocol_version {
6764
0
0
0
0
my $self = shift;
6765
0
0
my $version;
6766
0
0
0
if (@_) { $version = shift }
0
0
6767
0
0
else { $version = _protocol_version_from_string($protocol_current) }
6768
0
0
0
return ($version >> $protocol_version_major_shift, $version & $protocol_version_minor_mask) if wantarray;
6769
0
0
return $version
6770
}
6771
6772
sub _profile_version_from_string {
6773
15
15
3326
my $str = shift;
6774
15
50
40
croak '_profile_version_from_string() expects a string as argument' unless $str;
6775
15
49
my ($major, $minor) = split /\./, $str, 2;
6776
15
100
45
if ($minor >= 100) { $major += 1 } # kludge to deal with three-digit minor versions
7
13
6777
15
43
return $major * $profile_version_scale + $minor % $profile_version_scale
6778
}
6779
6780
sub profile_version {
6781
19
19
0
7484
my $self = shift;
6782
19
27
my $version;
6783
19
100
39
if (@_) {
6784
16
25
$version = shift;
6785
16
100
65
$version = _profile_version_from_string($version) if $version =~ /\./
6786
3
7
} else { $version = _profile_version_from_string($profile_current) }
6787
6788
19
100
40
if (wantarray) {
6789
12
28
my $major = int($version / $profile_version_scale);
6790
12
17
my $minor = $version % $profile_version_scale;
6791
12
100
26
if ($version >= 2200) { # kludge to deal with three-digit minor versions
6792
5
7
$major -= 1;
6793
5
7
$minor += 100
6794
}
6795
12
37
return ($major, $minor)
6796
}
6797
7
16
return $version
6798
}
6799
6800
sub profile_version_string {
6801
5
5
1
2066
my $self = shift;
6802
5
12
my @version;
6803
5
100
21
if (blessed $self) {
6804
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};
6805
1
50
3
croak 'object method expects no arguments' if @_;
6806
@version = profile_version(undef, $self->{profile_version} )
6807
1
4
} else {
6808
4
10
@version = profile_version(undef, @_)
6809
}
6810
5
30
return sprintf '%u.%03u', @version
6811
}
6812
6813
0
0
0
0
sub profile_version_major { profile_version( @_) };
6814
0
0
1
0
sub protocol_version_string { sprintf '%u.%u', ( protocol_version(@_) ) }
6815
0
0
0
0
sub protocol_version_major { protocol_version(@_) };
6816
6817
# CRC calculation routine taken from
6818
# Haruhiko Okumura, C gengo ni yoru algorithm dai jiten (1st ed.), GijutsuHyouronsha 1991.
6819
6820
my $crc_poly = 2 ** 16 + 2 ** 15 + 2 ** 2 + 2 ** 0; # CRC-16
6821
my ($crc_poly_deg, $crc_poly_rev);
6822
my ($x, $y, $i);
6823
for ($crc_poly_deg = 0, $x = $crc_poly ; $x >>= 1 ;) {
6824
++$crc_poly_deg;
6825
}
6826
my $crc_octets = int($crc_poly_deg / 8 + 0.5);
6827
for ($crc_poly_rev = 0, $y = 1, $x = 2 ** ($crc_poly_deg - 1) ; $x ;) {
6828
$crc_poly_rev |= $y if $x & $crc_poly;
6829
$y <<= 1;
6830
$x >>= 1;
6831
}
6832
my @crc_table = ();
6833
for ($i = 0 ; $i < 2 ** 8 ; ++$i) {
6834
my $r = $i;
6835
my $j;
6836
for ($j = 0 ; $j < 8 ; ++$j) {
6837
if ($r & 1) {
6838
$r = ($r >> 1) ^ $crc_poly_rev;
6839
} else {
6840
$r >>= 1;
6841
}
6842
}
6843
$crc_table[$i] = $r;
6844
}
6845
6846
sub dump {
6847
0
0
0
0
my ($self, $s, $FH) = @_;
6848
0
0
my ($i, $d);
6849
0
0
for ($i = 0 ; $i < length($s) ;) {
6850
0
0
$FH->printf(' %03u', ord(substr($s, $i++, 1)));
6851
}
6852
}
6853
6854
sub safe_isa {
6855
4
4
0
7
eval {$_[0]->isa($_[1])};
4
57
6856
}
6857
6858
sub file_read {
6859
12
12
0
16
my $self = shift;
6860
12
100
24
if (@_) {
6861
4
17
$self->{file_read} = $_[0];
6862
} else {
6863
8
31
$self->{file_read};
6864
}
6865
}
6866
6867
sub file_size {
6868
313
313
0
379
my $self = shift;
6869
313
100
449
if (@_) {
6870
3
10
$self->{file_size} = $_[0];
6871
} else {
6872
310
531
$self->{file_size};
6873
}
6874
}
6875
6876
sub file_processed {
6877
305
305
0
727
my $self = shift;
6878
305
100
431
if (@_) {
6879
2
5
$self->{file_processed} = $_[0];
6880
} else {
6881
303
429
$self->{file_processed};
6882
}
6883
}
6884
6885
sub offset {
6886
1651
1651
1
1903
my $self = shift;
6887
1651
100
2297
if (@_) {
6888
345
557
$self->{offset} = $_[0];
6889
} else {
6890
1306
2155
$self->{offset};
6891
}
6892
}
6893
6894
sub buffer {
6895
1252
1252
0
1494
my $self = shift;
6896
1252
50
1851
if (@_) {
6897
0
0
$self->{buffer} = $_[0];
6898
} else {
6899
1252
1689
$self->{buffer};
6900
}
6901
}
6902
6903
sub maybe_chained {
6904
2
2
0
4
my $self = shift;
6905
2
50
5
if (@_) {
6906
0
0
$self->{maybe_chained} = $_[0];
6907
} else {
6908
2
11
$self->{maybe_chained};
6909
}
6910
}
6911
6912
sub really_clear_buffer {
6913
2
2
0
5
my $self = shift;
6914
2
5
my $buffer = $self->{buffer};
6915
6916
2
50
6
$self->crc_calc(length($$buffer)) if !defined $self->crc;
6917
2
6
$self->file_processed($self->file_processed + $self->offset);
6918
2
5
substr($$buffer, 0, $self->offset) = '';
6919
2
4
$self->offset(0);
6920
}
6921
6922
sub cp_fit {
6923
2
2
0
4
my $self = shift;
6924
2
50
6
if (@_) {
6925
0
0
$self->{cp_fit} = $_[0];
6926
} else {
6927
2
18
$self->{cp_fit};
6928
}
6929
}
6930
6931
sub cp_fit_FH {
6932
3
3
0
6
my $self = shift;
6933
3
50
12
if (@_) {
6934
0
0
$self->{cp_fit_FH} = $_[0];
6935
} else {
6936
3
9
$self->{cp_fit_FH};
6937
}
6938
}
6939
6940
sub clear_buffer {
6941
5
5
0
10
my $self = shift;
6942
5
100
10
if ($self->offset > 0) {
6943
2
50
10
if ($self->cp_fit) {
6944
0
0
my $FH = $self->cp_fit_FH;
6945
6946
0
0
0
0
if (&safe_isa($FH, 'FileHandle') && $FH->opened) {
6947
0
0
my $buffer = $self->buffer;
6948
6949
0
0
$FH->print(substr($$buffer, 0, $self->offset));
6950
0
0
$FH->flush;
6951
0
0
$self->really_clear_buffer;
6952
}
6953
} else {
6954
2
9
$self->really_clear_buffer;
6955
}
6956
}
6957
}
6958
6959
=head2 Object methods
6960
6961
=over 4
6962
6963
=item file(I)
6964
6965
sets the name I of a .FIT file.
6966
6967
=back
6968
6969
=cut
6970
6971
sub file {
6972
7
7
1
1740
my $self = shift;
6973
7
100
21
if (@_) {
6974
3
11
$self->{file} = $_[0];
6975
} else {
6976
4
11
$self->{file};
6977
}
6978
}
6979
6980
=over 4
6981
6982
=item open()
6983
6984
opens the .FIT file.
6985
6986
=back
6987
6988
=cut
6989
6990
sub open {
6991
3
3
1
15
my $self = shift;
6992
3
8
my $fn = $self->file;
6993
6994
3
50
12
if ($fn ne '') {
6995
3
11
my $FH = $self->FH;
6996
6997
3
50
19
if ($FH->open("< $fn")) {
6998
3
50
237
if (binmode $FH, ':raw') {
6999
3
10
1;
7000
} else {
7001
0
0
$self->error("binmode \$FH, ':raw': $!");
7002
}
7003
} else {
7004
0
0
$self->error("\$FH->open(\"< $fn\"): $!");
7005
}
7006
} else {
7007
0
0
$self->error('no file name given');
7008
}
7009
}
7010
7011
sub FH {
7012
11
11
0
22
my $self = shift;
7013
11
50
21
if (@_) {
7014
0
0
$self->{FH} = $_[0];
7015
} else {
7016
11
69
$self->{FH};
7017
}
7018
}
7019
7020
sub EOF {
7021
1
1
2
my $self = shift;
7022
1
50
3
if (@_) {
7023
1
2
$self->{EOF} = $_[0];
7024
} else {
7025
0
0
$self->{EOF};
7026
}
7027
}
7028
7029
sub end_of_chunk {
7030
1
1
0
2
my $self = shift;
7031
1
50
3
if (@_) {
7032
1
5
$self->{end_of_chunk} = $_[0];
7033
} else {
7034
0
0
$self->{end_of_chunk};
7035
}
7036
}
7037
7038
sub fill_buffer {
7039
644
644
0
936
my ($self, $req) = @_;
7040
644
957
my $buffer = $self->buffer;
7041
7042
644
1150
while (length($$buffer) - $self->offset < $req) {
7043
5
18
$self->clear_buffer;
7044
5
11
my $n = $self->FH->read($$buffer, BUFSIZ, length($$buffer));
7045
7046
5
100
359
if ($n > 0) {
7047
4
19
$self->file_read($self->file_read + $n);
7048
7049
4
100
13
if (defined $self->file_size) {
7050
1
50
4
if (defined $self->crc) {
7051
1
5
$self->crc_calc($n);
7052
} else {
7053
0
0
$self->crc_calc(length($$buffer));
7054
}
7055
}
7056
} else {
7057
1
50
55
if (defined $n) {
7058
1
6
$self->error("unexpected EOF");
7059
1
4
$self->EOF(1);
7060
} else {
7061
0
0
$self->error("read(FH): $!");
7062
}
7063
return undef
7064
1
5
}
7065
}
7066
643
1206
return 1
7067
}
7068
7069
my $header_template = 'C C v V V';
7070
my $header_length = length(pack($header_template));
7071
7072
sub FIT_HEADER_LENGTH {
7073
0
0
1
0
$header_length;
7074
}
7075
7076
my $FIT_signature_string = '.FIT';
7077
my $FIT_signature = unpack('V', $FIT_signature_string);
7078
7079
my $header_crc_template = 'v';
7080
my $header_crc_length = length(pack($header_crc_template));
7081
7082
=over 4
7083
7084
=item fetch_header()
7085
7086
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.
7087
7088
=back
7089
7090
=cut
7091
7092
sub fetch_header {
7093
3
3
1
19
my $self = shift;
7094
3
50
11
$self->fill_buffer($header_length) || return undef;
7095
7096
3
13
my $buffer = $self->buffer;
7097
3
14
my $h_min = substr($$buffer, $self->offset, $header_length);
7098
3
24
my ($h_len, $proto_ver, $prof_ver, $f_len, $sig) = unpack($header_template, $h_min);
7099
7100
3
19
$self->offset($self->offset + $header_length);
7101
7102
3
50
11
if ($h_len < $header_length) {
7103
0
0
$self->error("not a .FIT header ($h_len < $header_length)");
7104
0
0
();
7105
} else {
7106
3
6
my $extra;
7107
7108
3
50
12
if ($h_len > $header_length) {
7109
3
50
14
$self->fill_buffer($h_len - $header_length) || return undef;
7110
3
11
$extra = substr($$buffer, $self->offset, $h_len - $header_length);
7111
3
18
$self->offset($self->offset + $h_len - $header_length);
7112
}
7113
7114
3
50
11
if ($sig != $FIT_signature) {
7115
$self->error("not a .FIT header (" .
7116
0
0
0
0
join('', map {($_ ne "\\" && 0x20 >= ord($_) && ord($_) <= 0x7E) ? $_ : sprintf("\\x%02X", ord($_))} split //, pack('V', $sig))
0
0
7117
. " ne '$FIT_signature_string')");
7118
0
0
();
7119
} else {
7120
3
9
my ($crc_expected, $crc_calculated);
7121
7122
3
50
33
33
if ($proto_ver >= $protocol_version_header_crc_started && length($extra) >= $header_crc_length) {
7123
3
11
$crc_expected = unpack($header_crc_template, substr($extra, -$header_crc_length));
7124
3
10
substr($extra, -$header_crc_length) = '';
7125
3
17
$crc_calculated = $self->crc_of_string(0, \$h_min, 0, $header_length);
7126
}
7127
7128
3
7
my $f_size = $f_len + $h_len;
7129
7130
3
23
$self->file_size($f_size);
7131
7132
3
50
9
unless (defined $self->crc) {
7133
3
10
$self->crc(0);
7134
3
11
$self->crc_calc(length($$buffer));
7135
}
7136
3
25
$self->{profile_version} = $prof_ver;
7137
7138
3
35
($f_size, $proto_ver, $prof_ver, $extra, $crc_expected, $crc_calculated);
7139
}
7140
}
7141
}
7142
7143
=over 4
7144
7145
=item fetch()
7146
7147
reads a message in the .FIT file, and returns C<1> on success, or C on failure or EOF.
7148
7149
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).
7150
7151
=back
7152
7153
=cut
7154
7155
sub fetch {
7156
302
302
1
31714
my $self = shift;
7157
302
100
533
$self->fill_buffer($crc_octets) or return undef;
7158
7159
301
465
my $buffer = $self->buffer;
7160
301
445
my $i = $self->offset;
7161
301
473
my $j = $self->file_processed + $i;
7162
7163
301
100
33
442
if ($j < $self->file_size) {
50
7164
300
506
my $record_header = ord(substr($$buffer, $i, 1));
7165
300
378
my $local_msg_type = -1;
7166
7167
300
50
614
if ($record_header & $rechd_mask_compressed_timestamp_header) {
100
7168
0
0
$local_msg_type = ($record_header & $rechd_mask_cth_local_message_type) >> $rechd_offset_cth_local_message_type
7169
} elsif ($record_header & $rechd_mask_definition_message) {
7170
36
127
$self->fetch_definition_message
7171
} else {
7172
264
336
$local_msg_type = $record_header & $rechd_mask_local_message_type
7173
}
7174
7175
300
100
457
if ($local_msg_type < 0) {
7176
36
101
1;
7177
} else {
7178
264
410
my $desc = $self->data_message_descriptor->[$local_msg_type];
7179
7180
264
50
447
if (ref $desc eq 'HASH') {
7181
264
426
$self->fetch_data_message($desc);
7182
} else {
7183
0
0
$self->error(sprintf("%d at %ld: not defined", $record_header, $j));
7184
}
7185
}
7186
} elsif (!$self->maybe_chained && $j > $self->file_size) {
7187
0
0
$self->trailing_garbages($self->trailing_garbages + length($$buffer) - $i);
7188
0
0
$self->offset(length($$buffer));
7189
0
0
1;
7190
} else {
7191
1
50
3
$self->crc_calc(length($$buffer)) if !defined $self->crc;
7192
7193
1
3
my ($crc_expected, $k);
7194
7195
1
6
for ($crc_expected = 0, $k = $crc_octets ; $k > 0 ;) {
7196
2
6
$crc_expected = ($crc_expected << 8) + ord(substr($$buffer, $i + --$k, 1));
7197
}
7198
7199
1
6
$self->crc_expected($crc_expected);
7200
1
4
$self->offset($i + $crc_octets);
7201
1
6
$self->end_of_chunk(1);
7202
1
2
!$self->maybe_chained;
7203
}
7204
}
7205
7206
sub error_callback { # consider making internal (_error_callback)
7207
0
0
0
0
my $self = shift;
7208
0
0
0
if (@_) {
7209
0
0
0
if (&safe_isa($_[0], 'CODE')) {
7210
0
0
$self->{error_callback_argv} = [@_[1 .. $#_]];
7211
0
0
$self->{error_callback} = $_[0];
7212
} else {
7213
0
0
undef;
7214
}
7215
} else {
7216
0
0
$self->{error_callback};
7217
}
7218
}
7219
7220
=over 4
7221
7222
=item error()
7223
7224
returns an error message recorded by a method.
7225
7226
=back
7227
7228
=cut
7229
7230
sub error {
7231
1
1
1
2
my $self = shift;
7232
1
50
5
if (@_) {
7233
1
2
my ($p, $fn, $l, $subr, $fit);
7234
7235
1
14
(undef, $fn, $l) = caller(0);
7236
1
40
($p, undef, undef, $subr) = caller(1);
7237
1
7
$fit = $self->file;
7238
1
50
7
$fit .= ': ' if $fit ne '';
7239
7240
1
7
$self->{error} = "${p}::$subr\#$l\@$fn: $fit$_[0]";
7241
7242
1
50
8
if (&safe_isa($self->{error_callback}, 'CODE')) {
7243
0
0
0
my $argv = &safe_isa($self->{error_callback_argv}, 'ARRAY') ? $self->{error_callback_argv} : [];
7244
7245
0
0
$self->{error_callback}->($self, @$argv);
7246
} else {
7247
1
3
undef;
7248
}
7249
} else {
7250
0
0
$self->{error};
7251
}
7252
}
7253
7254
=over 4
7255
7256
=item crc()
7257
7258
CRC-16 calculated from the contents of a .FIT file.
7259
7260
=back
7261
7262
=cut
7263
7264
sub crc {
7265
18
18
1
25
my $self = shift;
7266
18
100
39
if (@_) {
7267
7
18
$self->{crc} = $_[0];
7268
} else {
7269
11
39
$self->{crc};
7270
}
7271
}
7272
7273
sub crc_of_string {
7274
7
7
0
20
my ($self, $crc, $p, $b, $n) = @_;
7275
7
12
my $e = $b + $n;
7276
7
25
while ($b < $e) {
7277
27494
48296
$crc = ($crc >> 8) ^ $crc_table[($crc & (2 ** 8 - 1)) ^ ord(substr($$p, $b++, 1))];
7278
}
7279
7
42
$crc;
7280
}
7281
7282
sub crc_calc {
7283
4
4
0
11
my ($self, $m) = @_;
7284
4
17
my $over = $self->file_read - $self->file_size;
7285
4
100
15
$over = 0 if $over < 0;
7286
7287
4
50
12
if ($m > $over) {
7288
4
9
my $buffer = $self->buffer;
7289
4
12
$self->crc($self->crc_of_string($self->crc, $buffer, length($$buffer) - $m, $m - $over));
7290
}
7291
}
7292
7293
=over 4
7294
7295
=item crc_expected()
7296
7297
CRC-16 attached to the end of a .FIT file. Only available after all contents of the file has been read.
7298
7299
=back
7300
7301
=cut
7302
7303
sub crc_expected {
7304
1
1
1
3
my $self = shift;
7305
1
50
4
if (@_) {
7306
1
2
$self->{crc_expected} = $_[0];
7307
} else {
7308
0
0
$self->{crc_expected};
7309
}
7310
}
7311
7312
=over 4
7313
7314
=item trailing_garbages()
7315
7316
number of octets after CRC-16, 0 usually.
7317
7318
=back
7319
7320
=cut
7321
7322
sub trailing_garbages {
7323
0
0
1
0
my $self = shift;
7324
0
0
0
if (@_) {
7325
0
0
$self->{trailing_garbages} = $_[0];
7326
} else {
7327
0
0
$self->{trailing_garbages};
7328
}
7329
}
7330
7331
sub numeric_date_time {
7332
0
0
0
0
my $self = shift;
7333
0
0
0
if (@_) {
7334
0
0
$self->{numeric_date_time} = $_[0];
7335
} else {
7336
0
0
$self->{numeric_date_time};
7337
}
7338
}
7339
7340
sub date_string {
7341
0
0
0
0
my ($self, $time) = @_;
7342
0
0
0
my ($s, $mi, $h, $d, $mo, $y, $gmt) = $self->use_gmtime ? ((gmtime($time))[0 .. 5], 'Z') : (localtime($time))[0 .. 5];
7343
0
0
sprintf('%04u-%02u-%02uT%02u:%02u:%02u%s', $y + 1900, $mo + 1, $d, $h, $mi, $s, $gmt);
7344
}
7345
7346
sub named_type_value {
7347
0
0
0
0
my ($self, $type_name, $val) = @_;
7348
0
0
my $typedesc = $named_type{$type_name};
7349
7350
0
0
0
if (ref $typedesc ne 'HASH') {
0
0
7351
0
0
$self->error("$type_name is not a named type");
7352
} elsif ($typedesc->{_mask}) {
7353
0
0
0
if ($val !~ /^[-+]?\d+$/) {
7354
0
0
my $num = 0;
7355
7356
0
0
for my $expr (split /,/, $val) {
7357
0
0
$expr =~ s/^.*=//;
7358
7359
0
0
0
if ($expr =~ s/^0[xX]//) {
7360
0
0
$num |= hex($expr);
7361
} else {
7362
0
0
$num |= $expr + 0;
7363
}
7364
}
7365
7366
0
0
$num;
7367
} else {
7368
0
0
my $mask = 0;
7369
0
0
my @key;
7370
7371
0
0
for my $key (sort {$typedesc->{$b} <=> $typedesc->{$a}} grep {/^[A-Za-z]/} keys %$typedesc) {
0
0
0
0
7372
0
0
push @key, $key . '=' . ($val & $typedesc->{$key});
7373
0
0
$mask |= $typedesc->{$key};
7374
}
7375
7376
0
0
my $rest = $val & ~$mask & ((1 << ($size[$typedesc->{_base_type}] * 8)) - 1);
7377
7378
0
0
0
if ($rest) {
0
7379
0
0
my $width = $size[$typedesc->{_base_type}] * 2;
7380
7381
0
0
join(',', @key, sprintf("0x%0${width}X", $rest));
7382
} elsif (@key) {
7383
0
0
join(',', @key);
7384
} else {
7385
0
0
0;
7386
}
7387
}
7388
} elsif ($type_name eq 'date_time') {
7389
0
0
0
0
if ($val !~ /^[-+]?\d+$/) {
0
7390
0
0
my ($y, $mo, $d, $h, $mi, $s, $gmt) = $val =~ /(\d+)\D+(\d+)\D+(\d+)\D+(\d+)\D+(\d+)\D+(\d+)([zZ]?)/;
7391
7392
0
0
0
($gmt ne '' ? timegm($s, $mi, $h, $d, $mo - 1, $y - 1900) : timelocal($s, $mi, $h, $d, $mo - 1, $y - 1900)) + $typedesc->{_offset};
7393
} elsif ($val >= $typedesc->{_min} && $val != $invalid[$typedesc->{_base_type}]) {
7394
0
0
0
if ($self->numeric_date_time) {
7395
0
0
$val - $typedesc->{_offset};
7396
} else {
7397
0
0
$self->date_string($val - $typedesc->{_offset});
7398
}
7399
} else {
7400
0
0
undef;
7401
}
7402
} else {
7403
0
0
$typedesc->{$val};
7404
}
7405
}
7406
7407
sub data_message_descriptor {
7408
300
300
0
362
my $self = shift;
7409
7410
300
50
437
if (@_) {
7411
0
0
$self->{data_message_descriptor} = $_[0];
7412
} else {
7413
300
100
591
$self->{data_message_descriptor} = [] if ref $self->{data_message_descriptor} ne 'ARRAY';
7414
300
555
$self->{data_message_descriptor};
7415
}
7416
}
7417
7418
sub data_message_callback {
7419
46
46
0
75
$_[0]->{data_message_callback};
7420
}
7421
7422
=over 4
7423
7424
=item data_message_callback_by_num(I, I[, I, ...])
7425
7426
register a function I which is called when a data message with the messag number I is fetched.
7427
7428
=back
7429
7430
=cut
7431
7432
my $msgnum_anon = $invalid[FIT_UINT16];
7433
my $msgname_anon = '';
7434
7435
sub data_message_callback_by_num {
7436
0
0
1
0
my $self = shift;
7437
0
0
my $num = shift;
7438
0
0
my $cbmap = $self->data_message_callback;
7439
0
0
my ($msgtype, $name);
7440
7441
0
0
0
if ($num == $msgnum_anon) {
0
0
7442
0
0
0
if (@_) {
7443
0
0
0
if (ref $_[0] eq 'CODE') {
7444
0
0
$cbmap->{$msgname_anon} = $cbmap->{$msgnum_anon} = [@_];
7445
} else {
7446
0
0
$self->error('not a CODE');
7447
}
7448
} else {
7449
0
0
my %res;
7450
0
0
foreach $num (keys %msgtype_by_num) {
7451
0
0
my $cb = $cbmap->{$num};
7452
0
0
0
ref $cb eq 'ARRAY' and $res{$num} = [@$cb];
7453
}
7454
0
0
\%res;
7455
}
7456
} elsif (!defined($msgtype = $msgtype_by_num{$num})) {
7457
0
0
$self->error("$num is not a message type number");
7458
} elsif (@_) {
7459
0
0
0
if (ref $_[0] eq 'CODE') {
7460
0
0
$cbmap->{$num} = [@_];
7461
0
0
0
$msgtype->{_name} ne '' and $cbmap->{$msgtype->{_name}} = $cbmap->{$num};
7462
0
0
$cbmap->{$num};
7463
} else {
7464
0
0
$self->error('not a CODE');
7465
}
7466
} else {
7467
0
0
my $cb = $cbmap->{$num};
7468
0
0
0
ref $cb eq 'ARRAY' ? [@$cb] : [];
7469
}
7470
}
7471
7472
=over 4
7473
7474
=item data_message_callback_by_name(I, I[, I, ...])
7475
7476
register a function I which is called when a data message with the name I is fetched.
7477
7478
=back
7479
7480
=cut
7481
7482
sub data_message_callback_by_name {
7483
10
10
1
45
my $self = shift;
7484
10
17
my $name = shift;
7485
10
21
my $cbmap = $self->data_message_callback;
7486
10
14
my $msgtype;
7487
7488
10
100
55
if ($name eq $msgname_anon) {
50
50
7489
2
100
7
if (@_) {
7490
1
50
12
if (ref $_[0] eq 'CODE') {
7491
1
6
$cbmap->{$msgname_anon} = $cbmap->{$msgnum_anon} = [@_];
7492
} else {
7493
0
0
$self->error('not a CODE');
7494
}
7495
} else {
7496
1
2
my %res;
7497
1
26
foreach $name (keys %msgtype_by_name) {
7498
98
113
my $cb = $cbmap->{$name};
7499
98
100
185
ref $cb eq 'ARRAY' and $res{$name} = [@$cb];
7500
}
7501
1
8
\%res;
7502
}
7503
} elsif (!defined($msgtype = $msgtype_by_name{$name})) {
7504
0
0
$self->error("$name is not a message type name");
7505
} elsif (@_) {
7506
8
50
24
if (ref $_[0] eq 'CODE') {
7507
8
41
$cbmap->{$msgtype->{_number}} = $cbmap->{$name} = [@_];
7508
} else {
7509
0
0
$self->error('not a CODE');
7510
}
7511
} else {
7512
0
0
my $cb = $cbmap->{$name};
7513
0
0
0
ref $cb eq 'ARRAY' ? [@$cb] : [];
7514
}
7515
}
7516
7517
sub undocumented_field_name {
7518
208
208
0
352
my ($self, $index, $size, $type, $i_string) = @_;
7519
# 'xxx' . $i_string . '_' . $index . '_' . $size . '_' . $type;
7520
208
481
'xxx' . $index;
7521
}
7522
7523
sub syscallback_devdata_id {
7524
0
0
0
0
my ($self, $desc, $v) = @_;
7525
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)};
7526
0
0
my ($emsg, $warn);
7527
7528
0
0
0
0
if (!defined $i_id) {
0
0
7529
0
0
$emsg = "no application_id";
7530
0
0
$warn = 1;
7531
} elsif ($T_id != FIT_UINT8 && $T_id != FIT_BYTE) {
7532
0
0
croak "There is a bug here, this should be resolved soon";
7533
# $type_name has not been declared in this scope need to figure out what it should be
7534
# $emsg = "base type of application_id is $type_name [$T_id] ($T_id)";
7535
} elsif (!defined $i_index) {
7536
0
0
$emsg = "no developer_data_index";
7537
}
7538
7539
0
0
0
if ($emsg ne '') {
7540
0
0
0
if ($warn) {
7541
0
0
$self->error("suspicious developer data id message ($emsg)");
7542
} else {
7543
0
0
$self->error("broken developer data id message ($emsg)");
7544
0
0
return undef;
7545
}
7546
}
7547
7548
0
0
my $devdata_by_index = $self->{devdata_by_index};
7549
0
0
0
ref $devdata_by_index eq 'HASH' or $devdata_by_index = $self->{devdata_by_index} = +{};
7550
7551
0
0
my $devdata_by_id = $self->{devdata_by_id};
7552
0
0
0
ref $devdata_by_id eq 'HASH' or $devdata_by_id = $self->{devdata_by_id} = +{};
7553
7554
0
0
my $id;
7555
0
0
0
if ($T_id == FIT_UINT8) {
7556
0
0
$id = pack('C*', @$v[$i_id .. ($i_id + $c_id - 1)]);
7557
} else {
7558
0
0
$id = $v->[$i_id];
7559
}
7560
7561
0
0
my %devdata = (id => $id, index => $v->[$i_index]);
7562
0
0
$devdata_by_id->{$devdata{id}} = $devdata_by_index->{$devdata{index}} = \%devdata;
7563
}
7564
7565
sub syscallback_devdata_field_desc {
7566
0
0
0
0
my ($self, $desc, $v) = @_;
7567
7568
my ($i_index, $I_index, $i_field_num, $I_field_num,
7569
$i_base_type_id, $T_base_type_id, $I_base_type_id,
7570
$i_field_name, $T_field_name, $c_field_name)
7571
0
0
= @$desc{qw(i_developer_data_index I_developer_data_index i_field_definition_number I_field_definition_number
7572
i_fit_base_type_id T_fit_base_type_id I_fit_base_type_id
7573
i_field_name T_field_name c_field_name)};
7574
7575
0
0
my ($emsg, $warn, $o_name);
7576
7577
0
0
0
0
if (!defined $i_index) {
0
0
0
0
0
7578
0
0
$emsg = 'no developer_data_index';
7579
} elsif (!defined $i_field_num) {
7580
0
0
$emsg = 'no field_num';
7581
} elsif (!defined $i_base_type_id) {
7582
0
0
$emsg = 'no base_type_id';
7583
} elsif ($T_base_type_id != FIT_UINT8) {
7584
0
0
croak "There is a bug here, this should be resolved soon";
7585
# $type_name has not been declared in this scope need to figure out what it should be
7586
# $emsg = "base type of base_type_id is $type_name [$T_base_type_id] ($T_base_type_id)";
7587
} elsif (!defined $i_field_name) {
7588
0
0
$emsg = 'no field_name';
7589
0
0
$warn = 1;
7590
} elsif ($T_field_name != FIT_STRING || $c_field_name <= 0) {
7591
0
0
$emsg = "field_name is not a non-empty string";
7592
0
0
$warn = 1;
7593
} else {
7594
0
0
$o_name = $self->string_value($v, $i_field_name, $c_field_name);
7595
}
7596
7597
0
0
0
if ($emsg ne '') {
7598
0
0
0
if ($warn) {
7599
0
0
$self->error("suspicious field description message ($emsg)");
7600
} else {
7601
0
0
$self->error("broken field description message ($emsg)");
7602
0
0
return undef;
7603
}
7604
}
7605
7606
0
0
my $base_type = $v->[$i_base_type_id];
7607
7608
0
0
0
if ($base_type == $I_base_type_id) {
7609
0
0
$self->error("invalid base type ($base_type)");
7610
0
0
return undef;
7611
}
7612
7613
0
0
0
if ($base_type < 0) {
7614
0
0
$self->error("unknown base type ($base_type)");
7615
0
0
return undef;
7616
}
7617
7618
0
0
$base_type &= $deffld_mask_type;
7619
7620
0
0
0
unless ($base_type <= FIT_BASE_TYPE_MAX) {
7621
0
0
$self->error("unknown base type ($base_type)");
7622
0
0
return undef;
7623
}
7624
7625
0
0
my $devdata_by_index = $self->{devdata_by_index};
7626
7627
0
0
0
unless (ref $devdata_by_index eq 'HASH') {
7628
0
0
$self->error('no developer data id message before a field description message');
7629
0
0
return undef;
7630
}
7631
7632
0
0
my $index = $v->[$i_index];
7633
7634
0
0
0
if ($index == $I_index) {
7635
0
0
$self->error("invalid developer data index ($index)");
7636
0
0
return undef;
7637
}
7638
7639
0
0
my $num = $v->[$i_field_num];
7640
7641
0
0
0
if ($num == $I_field_num) {
7642
0
0
$self->error("invalid field definition number ($num)");
7643
0
0
return undef;
7644
}
7645
7646
0
0
my $devdata = $devdata_by_index->{$index};
7647
7648
0
0
0
unless (ref $devdata eq 'HASH') {
7649
0
0
$self->error("No developer data id message with the index $index before a field description message");
7650
0
0
return undef;
7651
}
7652
7653
0
0
my $field_desc_by_num = $devdata->{field_desc_by_num};
7654
0
0
0
ref $field_desc_by_num eq 'HASH' or $field_desc_by_num = $devdata->{field_desc_by_num} = +{};
7655
7656
0
0
my $field_desc_by_name = $devdata->{field_desc_by_name};
7657
0
0
0
ref $field_desc_by_name eq 'HASH' or $field_desc_by_name = $devdata->{field_desc_by_name} = +{};
7658
7659
0
0
my $name = $o_name;
7660
7661
0
0
0
if (defined $name) {
7662
0
0
$name =~ s/\s+/_/g;
7663
0
0
$name =~ s/\W/sprintf('_%02x_', ord($&))/ge;
0
0
7664
}
7665
7666
0
0
my %fdesc = (
7667
'_index' => $index,
7668
'_num' => $num,
7669
'_name' => $name,
7670
'field_name' => $o_name,
7671
'_type' => $base_type,
7672
);
7673
7674
0
0
for my $i_aname (grep {/^i_/} keys %$desc) {
0
0
7675
0
0
0
if ($i_aname !~ /^i_(developer_data_index|field_definition_number|fit_base_type_id|field_name)$/) {
7676
0
0
my $i = $desc->{$i_aname};
7677
0
0
my $aname = $i_aname;
7678
7679
0
0
$aname =~ s/^i_//;
7680
7681
0
0
my $I_aname = 'I_' . $aname;
7682
0
0
my $T_aname = 'T_' . $aname;
7683
0
0
my $c_aname = 'c_' . $aname;
7684
7685
0
0
0
if ($desc->{$T_aname} == FIT_STRING) {
0
7686
0
0
$fdesc{$aname} = $self->string_value($v, $i, $desc->{$c_aname});
7687
} elsif ($v->[$i] != $desc->{$I_aname}) {
7688
0
0
$fdesc{$aname} = $v->[$i];
7689
}
7690
}
7691
}
7692
7693
0
0
0
defined $name and $field_desc_by_name->{$name} = \%fdesc;
7694
0
0
$field_desc_by_num->{$num} = \%fdesc;
7695
}
7696
7697
sub add_endian_converter {
7698
858
858
0
1502
my ($self, $endian, $type, $c, $i_string, $cvt) = @_;
7699
7700
858
50
33
1694
if ($endian != $my_endian && $size[$type] > 1) {
7701
0
0
my ($p, $unp, $n);
7702
7703
0
0
0
if ($size[$type] == 2) {
0
7704
0
0
($p, $unp) = (qw(n v));
7705
} elsif ($size[$type] == 4) {
7706
0
0
($p, $unp) = (qw(N V));
7707
} else {
7708
0
0
($p, $unp, $n) = (qw(N V), 2);
7709
}
7710
7711
0
0
push @$cvt, $p . $n, $unp . $n, $i_string, $size[$type], $c;
7712
0
0
1;
7713
} else {
7714
858
1126
0;
7715
}
7716
}
7717
7718
sub fetch_definition_message {
7719
36
36
0
59
my $self = shift;
7720
7721
36
50
59
$self->fill_buffer($defmsg_min_length) || return undef;
7722
7723
36
59
my $buffer = $self->buffer;
7724
36
61
my $i = $self->offset;
7725
36
130
my ($record_header, $reserved, $endian, $msgnum, $nfields) = unpack($defmsg_min_template, substr($$buffer, $i, $defmsg_min_length));
7726
7727
36
50
70
$endian = $endian ? 1 : 0;
7728
36
84
$self->offset($i + $defmsg_min_length);
7729
7730
36
49
my $len = $nfields * $deffld_length;
7731
7732
36
50
61
$self->fill_buffer($len) || return undef;
7733
36
61
$i = $self->offset;
7734
36
50
63
$msgnum = unpack('n', pack('v', $msgnum)) if $endian != $my_endian;
7735
7736
36
135
my $msgtype = $msgtype_by_num{$msgnum};
7737
36
70
my $cbmap = $self->data_message_callback;
7738
36
51
my $e = $i + $len;
7739
36
50
my ($cb, %desc, $i_array, $i_array_t, $i_string, @cvt, @pi);
7740
7741
36
85
$desc{local_message_type} = $record_header & $rechd_mask_local_message_type;
7742
36
87
$desc{message_number} = $msgnum;
7743
36
100
100
201
$desc{message_name} = $msgtype->{_name} if ref $msgtype eq 'HASH' && exists $msgtype->{_name};
7744
36
50
82
$cb = $cbmap->{$msgnum} if ref $cbmap->{$msgnum} eq 'ARRAY';
7745
36
50
80
$cb = $cbmap->{$msgnum_anon} if ref $cb ne 'ARRAY';
7746
36
100
71
$desc{callback} = $cb if ref $cb eq 'ARRAY';
7747
36
49
$desc{endian} = $endian;
7748
36
59
$desc{template} = 'C';
7749
36
72
$self->data_message_descriptor->[$desc{local_message_type}] = \%desc;
7750
7751
36
83
for ($i_array = $i_array_t = $i_string = 1 ; $i + $deffld_length <= $e ; $i += $deffld_length) {
7752
858
2103
my ($index, $size, $type) = unpack($deffld_template, substr($$buffer, $i, $deffld_length));
7753
858
1238
my ($name, $tname, %attr, );
7754
7755
858
100
1492
if (ref $msgtype eq 'HASH') {
7756
832
1748
my $fldtype = $msgtype->{$index};
7757
7758
832
100
1348
if (ref $fldtype eq 'HASH') {
7759
650
3484
%attr = %$fldtype;
7760
650
1235
($name, $tname) = @attr{qw(name type_name)};
7761
650
868
delete $attr{name};
7762
650
843
delete $attr{type_name};
7763
}
7764
}
7765
7766
858
100
1529
$name = $self->undocumented_field_name($index, $size, $type, $i_string) if !defined $name;
7767
858
1476
$desc{$index} = $name;
7768
858
1112
$type &= $deffld_mask_type;
7769
7770
858
1408
my $c = int($size / $size[$type] + 0.5);
7771
7772
858
1870
$desc{'i_' . $name} = $i_array;
7773
858
1584
$desc{'o_' . $name} = $i_string;
7774
858
1765
$desc{'c_' . $name} = $c;
7775
858
1867
$desc{'s_' . $name} = $size[$type];
7776
858
100
1935
$desc{'a_' . $name} = \%attr if %attr;
7777
858
100
1549
$desc{'t_' . $name} = $tname if defined $tname;
7778
858
1569
$desc{'T_' . $name} = $type;
7779
858
2026
$desc{'N_' . $name} = $index;
7780
858
1557
$desc{'I_' . $name} = $invalid[$type];
7781
7782
858
1897
$self->add_endian_converter($endian, $type, $c, $i_string, \@cvt);
7783
7784
858
1120
$i_array += $c;
7785
858
954
$i_string += $size;
7786
858
1355
$desc{template} .= ' ' . $template[$type];
7787
7788
858
50
1416
if ($packfactor[$type] > 1) {
7789
0
0
push @pi, $i_array_t, $c, $i_array;
7790
0
0
$c *= $packfactor[$type];
7791
}
7792
7793
858
100
1284
$desc{template} .= $c if $c > 1;
7794
858
1719
$i_array_t += $c;
7795
}
7796
7797
36
68
$desc{template_without_devdata} = $desc{template};
7798
36
58
$desc{devdata_first} = $i_array;
7799
36
63
$desc{devdata_nfields} = 0;
7800
7801
36
50
76
if ($record_header & $rechd_mask_devdata_message) {
7802
0
0
$self->offset($e);
7803
0
0
0
$self->fill_buffer($devdata_min_length) || return undef;
7804
0
0
$i = $self->offset;
7805
0
0
($nfields) = unpack($devdata_min_template, substr($$buffer, $i, $devdata_min_length));
7806
0
0
$self->offset($i + $devdata_min_length);
7807
0
0
$len = $nfields * $devdata_deffld_length;
7808
0
0
0
$self->fill_buffer($len) || return undef;
7809
7810
0
0
my $devdata_by_index = $self->{devdata_by_index};
7811
0
0
my @emsg;
7812
7813
0
0
0
if (ref $devdata_by_index ne 'HASH') {
7814
0
0
push @emsg, 'No developer data id';
7815
0
0
$devdata_by_index = +{};
7816
}
7817
7818
0
0
for ($i = $self->offset, $e = $i + $len ; $i + $devdata_deffld_length <= $e ; $i += $devdata_deffld_length) {
7819
0
0
my ($fnum, $size, $index) = unpack($devdata_deffld_template, substr($$buffer, $i, $devdata_deffld_length));
7820
0
0
my $devdata = $devdata_by_index->{$index};
7821
0
0
my ($fdesc, $name, $type, %attr);
7822
7823
0
0
0
if (ref $devdata eq 'HASH') {
7824
0
0
my $fdesc_by_num = $devdata->{field_desc_by_num};
7825
7826
0
0
0
if (ref $fdesc_by_num eq 'HASH') {
7827
0
0
$fdesc = $fdesc_by_num->{$fnum};
7828
} else {
7829
0
0
push @emsg, "No field description message for developer data with index $index";
7830
}
7831
} else {
7832
0
0
push @emsg, "No developer data id with index $index";
7833
}
7834
7835
0
0
0
if (ref $fdesc eq 'HASH') {
7836
0
0
%attr = %$fdesc;
7837
0
0
($type, $name) = @attr{qw(_type _name)};
7838
} else {
7839
0
0
push @emsg, "No field with number $fnum for developer data with index $index";
7840
0
0
$type = FIT_UINT8;
7841
}
7842
7843
0
0
0
$name = $self->undocumented_field_name($fnum, $size, $type, $i_string) if !defined $name;
7844
0
0
$name = "${index}_${fnum}_$name";
7845
7846
0
0
my $c = int($size / $size[$type] + 0.5);
7847
7848
0
0
$desc{'i_' . $name} = $i_array;
7849
0
0
$desc{'o_' . $name} = $i_string;
7850
0
0
$desc{'c_' . $name} = $c;
7851
0
0
$desc{'s_' . $name} = $size[$type];
7852
0
0
0
$desc{'a_' . $name} = \%attr if %attr;
7853
0
0
$desc{'T_' . $name} = $type;
7854
0
0
$desc{'N_' . $name} = $fnum;
7855
0
0
$desc{'I_' . $name} = $invalid[$type];
7856
7857
0
0
$self->add_endian_converter($endian, $type, $c, $i_string, \@cvt);
7858
7859
0
0
$i_array += $c;
7860
0
0
$i_string += $size;
7861
0
0
$desc{template} .= ' ' . $template[$type];
7862
7863
0
0
0
if ($packfactor[$type] > 1) {
7864
0
0
push @pi, $type, $i_array_t, $c, $i_array;
7865
0
0
$c *= $packfactor[$type];
7866
}
7867
7868
0
0
0
$desc{template} .= $c if $c > 1;
7869
0
0
$i_array_t += $c;
7870
}
7871
7872
0
0
$desc{devdata_nfields} = $nfields;
7873
0
0
0
$self->error(join(' / ', @emsg)) if (@emsg);
7874
}
7875
7876
36
50
67
$desc{endian_converter} = \@cvt if @cvt;
7877
36
50
62
$desc{packfilter_index} = \@pi if @pi;
7878
36
59
$desc{message_length} = $i_string;
7879
36
54
$desc{array_length} = $i_array;
7880
36
86
$self->offset($e);
7881
36
78
return 1
7882
}
7883
7884
sub endian_convert {
7885
0
0
0
0
my ($self, $cvt, $buffer, $i) = @_;
7886
0
0
my $j;
7887
7888
0
0
for ($j = 4 ; $j < @$cvt ; $j += 5) {
7889
0
0
my ($b, $size, $c) = @$cvt[$j - 2, $j - 1, $j];
7890
7891
0
0
for ($b += $i ; $c > 0 ; $b += $size, --$c) {
7892
0
0
my @v = unpack($cvt->[$j - 3], substr($$buffer, $b, $size));
7893
0
0
my ($k, $l);
7894
7895
0
0
for ($k = 0, $l = $#v ; $k < $l ; ++$k, --$l) {
7896
0
0
@v[$k, $l] = @v[$l, $k];
7897
}
7898
0
0
substr($$buffer, $b, $size) = pack($cvt->[$j - 4], @v);
7899
}
7900
}
7901
}
7902
7903
sub last_timestamp {
7904
0
0
0
0
my $self = shift;
7905
0
0
0
if (@_) {
7906
0
0
$self->{last_timestamp} = $_[0];
7907
} else {
7908
0
0
$self->{last_timestamp};
7909
}
7910
}
7911
7912
sub fetch_data_message {
7913
264
264
0
377
my ($self, $desc) = @_;
7914
7915
264
50
416
$self->fill_buffer($desc->{message_length}) || return undef;
7916
264
50
499
$self->endian_convert($desc->{endian_converter}, $self->buffer, $self->offset) if ref $desc->{endian_converter} eq 'ARRAY';
7917
7918
264
384
my $buffer = $self->buffer;
7919
264
397
my $i = $self->offset;
7920
# unpack('f'/'d', ...) unpacks to NaN
7921
264
1085
my @v = unpack($desc->{template}, substr($$buffer, $i, $desc->{message_length}));
7922
7923
264
50
556
if (ref $desc->{packfilter_index} eq 'ARRAY') {
7924
0
0
my $piv = $desc->{packfilter_index};
7925
0
0
my ($i, $j);
7926
0
0
my @v_t = @v;
7927
7928
0
0
@v = ($v_t[0]);
7929
7930
0
0
for ($i = 1, $j = 3 ; $j < @$piv ; $j += 4) {
7931
0
0
my ($type, $i_array_t, $c, $i_array) = @$piv[($j - 3) .. $j];
7932
0
0
my $delta = $packfactor[$type];
7933
7934
0
0
0
$i < $i_array_t and push @v, @v_t[$i .. ($i_array_t - 1)];
7935
0
0
$i = $i_array_t + $c * $delta;
7936
7937
0
0
for (; $i_array_t < $i ; $i_array_t += $delta) {
7938
0
0
push @v, $unpackfilter[$type]->(@v_t[$i_array_t .. ($i_array_t + $delta - 1)]);
7939
}
7940
}
7941
}
7942
7943
264
565
$self->offset($i + $desc->{message_length});
7944
7945
264
346
my $cb = $desc->{callback};
7946
7947
264
100
432
if (ref $cb eq 'ARRAY') {
7948
21
50
44
$v[0] & $rechd_mask_compressed_timestamp_header and push @v, $self->last_timestamp + ($v[0] & $rechd_mask_cth_timestamp);
7949
21
92
$cb->[0]->($self, $desc, \@v, @$cb[1 .. $#$cb]);
7950
} else {
7951
243
571
1;
7952
}
7953
}
7954
7955
sub pack_data_message {
7956
0
0
0
0
my ($self, $desc, $v) = @_;
7957
0
0
my $drop_devdata = $self->drop_developer_data;
7958
7959
0
0
0
0
if ($drop_devdata && ($desc->{message_name} eq 'developer_data_id' || $desc->{message_name} eq 'field_description')) {
0
7960
0
0
'';
7961
} else {
7962
0
0
my $rv = $v;
7963
7964
0
0
0
if (ref $desc->{packfilter_index} eq 'ARRAY') {
7965
0
0
my @v = ($v->[0]);
7966
0
0
my $piv = $desc->{packfilter_index};
7967
0
0
my ($i, $j);
7968
7969
0
0
for ($i = 1, $j = 3 ; $j < @$piv ; $j += 4) {
7970
0
0
my ($type, $i_array_t, $c, $i_array) = @$piv[($j - 3) .. $j];
7971
7972
0
0
0
$i < $i_array and push @v, @$v[$i .. ($i_array - 1)];
7973
0
0
$i = $i_array + $c;
7974
7975
0
0
for (; $i_array < $i ; ++$i_array) {
7976
0
0
push @v, $packfilter[$type]->($v->[$i_array]);
7977
}
7978
}
7979
0
0
$rv = \@v;
7980
}
7981
7982
0
0
0
if ($drop_devdata) {
7983
0
0
0
if ($desc->{devdata_first} > 0) {
7984
0
0
pack($desc->{template_without_devdata}, @$rv[0 .. ($desc->{devdata_first} - 1)]);
7985
} else {
7986
0
0
'';
7987
}
7988
} else {
7989
0
0
pack($desc->{template}, @$rv);
7990
}
7991
}
7992
}
7993
7994
=over 4
7995
7996
=item switched(I, I, I)
7997
7998
returns real data type attributes for a C's union like field.
7999
8000
=back
8001
8002
=cut
8003
8004
sub switched {
8005
0
0
1
0
my ($self, $desc, $v, $sw) = @_;
8006
0
0
my ($keyv, $key, $attr);
8007
8008
0
0
0
if (ref $sw->{_by} eq 'ARRAY') {
8009
0
0
$keyv = $sw->{_by};
8010
} else {
8011
0
0
$keyv = [$sw->{_by}];
8012
}
8013
8014
0
0
for $key (@$keyv) {
8015
0
0
my $i_name = 'i_' . $key;
8016
0
0
my $val;
8017
8018
0
0
0
0
if (defined $desc->{$i_name} && ($val = $v->[$desc->{$i_name}]) != $desc->{'I_' . $key}) {
8019
0
0
my $key_tn = $desc->{'t_' . $key};
8020
8021
0
0
0
if (defined $key_tn) {
8022
0
0
my $t_val = $self->named_type_value($key_tn, $val);
8023
8024
0
0
0
$val = $t_val if defined $t_val;
8025
}
8026
8027
0
0
0
if (ref $sw->{$val} eq 'HASH') {
8028
0
0
$attr = $sw->{$val};
8029
0
0
last;
8030
}
8031
}
8032
}
8033
0
0
$attr;
8034
}
8035
8036
=over 4
8037
8038
=item string_value(I, I, I)
8039
8040
converts an array of character codes to a Perl string.
8041
8042
=back
8043
8044
=cut
8045
8046
sub string_value {
8047
0
0
1
0
my ($self, $v, $i, $n) = @_;
8048
0
0
my $j;
8049
8050
0
0
for ($j = 0 ; $j < $n ; ++$j) {
8051
0
0
0
$v->[$i + $j] == 0 && last;
8052
}
8053
0
0
pack('C*', @{$v}[$i .. ($i + $j - 1)]);
0
0
8054
}
8055
8056
sub value_processed {
8057
0
0
0
0
my ($self, $num, $attr) = @_;
8058
8059
0
0
0
if (ref $attr eq 'HASH') {
8060
0
0
my ($unit, $offset, $scale) = @{$attr}{qw(unit offset scale)};
0
0
8061
8062
0
0
0
0
$num /= $scale if defined $scale and $scale > 0;
8063
0
0
0
$num -= $offset if $offset;
8064
8065
0
0
0
0
if (defined $unit) {
0
8066
0
0
my $unit_tab = $self->unit_table($unit);
8067
8068
0
0
0
if (ref $unit_tab eq 'HASH') {
8069
0
0
my ($unit1, $offset1, $scale1) = @{$unit_tab}{qw(unit offset scale)};
0
0
8070
8071
0
0
0
if ($scale1 > 0) {
8072
0
0
$num /= $scale1;
8073
0
0
$scale += $scale1;
8074
}
8075
0
0
0
$num -= $offset1 if $offset1;
8076
0
0
0
$unit = $unit1 if $unit1 ne '';
8077
}
8078
8079
0
0
0
if ($scale > 0) {
0
8080
0
0
my $below_pt = int(log($scale + 9) / log(10));
8081
8082
0
0
0
if ($self->without_unit) {
8083
0
0
sprintf("%.${below_pt}f", $num);
8084
} else {
8085
0
0
sprintf("%.${below_pt}f %s", $num, $unit);
8086
}
8087
} elsif ($self->without_unit) {
8088
0
0
$num;
8089
} else {
8090
0
0
$num . " " . $unit;
8091
}
8092
} elsif (defined $scale and $scale > 0) {
8093
0
0
my $below_pt = int(log($scale + 9) / log(10));
8094
0
0
sprintf("%.${below_pt}f", $num);
8095
} else {
8096
0
0
$num;
8097
}
8098
} else {
8099
0
0
$num;
8100
}
8101
}
8102
8103
sub value_unprocessed {
8104
0
0
0
0
my ($self, $str, $attr) = @_;
8105
8106
0
0
0
if (ref $attr eq 'HASH') {
8107
0
0
my ($unit, $offset, $scale) = @{$attr}{qw(unit offset scale)};
0
0
8108
0
0
my $num = $str;
8109
8110
0
0
0
if ($unit ne '') {
8111
0
0
my $unit_tab = $self->unit_table($unit);
8112
8113
0
0
0
if (ref $unit_tab eq 'HASH') {
8114
0
0
my ($unit1, $offset1, $scale1) = @{$unit_tab}{qw(unit offset scale)};
0
0
8115
8116
0
0
0
$scale += $scale1 if $scale1 > 0;
8117
0
0
0
$offset += $offset1 if $offset1;
8118
0
0
0
$unit = $unit1 if $unit1 ne '';
8119
}
8120
8121
0
0
0
0
length($num) >= length($unit) && substr($num, -length($unit)) eq $unit
8122
and substr($num, -length($unit)) = '';
8123
}
8124
8125
0
0
0
$num += $offset if $offset;
8126
0
0
0
$num *= $scale if $scale > 0;
8127
0
0
$num;
8128
} else {
8129
0
0
$str;
8130
}
8131
}
8132
8133
=over 4
8134
8135
=item value_cooked(I, I, I, I)
8136
8137
converts I to a (hopefully) human readable form.
8138
8139
=item value_uncooked(I, I, I, I)
8140
8141
converts a human readable representation of a datum to an original form.
8142
8143
=back
8144
8145
=cut
8146
8147
sub value_cooked {
8148
0
0
1
0
my ($self, $tname, $attr, $invalid, $val) = @_;
8149
8150
0
0
0
if ($val == $invalid) {
8151
0
0
$val;
8152
} else {
8153
0
0
0
if (defined $tname) {
8154
0
0
my $vname = $self->named_type_value($tname, $val);
8155
8156
0
0
0
defined $vname && return $vname;
8157
}
8158
8159
0
0
0
if (ref $attr eq 'HASH') {
8160
0
0
$self->value_processed($val, $attr);
8161
} else {
8162
0
0
$val;
8163
}
8164
}
8165
}
8166
8167
sub value_uncooked {
8168
0
0
1
0
my ($self, $tname, $attr, $invalid, $val) = @_;
8169
8170
0
0
0
if ($val !~ /^[-+]?\d+$/) {
8171
0
0
0
if ($tname ne '') {
8172
0
0
my $vnum = $self->named_type_value($tname, $val);
8173
8174
0
0
0
defined $vnum && return $vnum;
8175
}
8176
8177
0
0
0
if (ref $attr eq 'HASH') {
8178
0
0
$self->value_unprocessed($val, $attr);
8179
} else {
8180
0
0
$val;
8181
}
8182
} else {
8183
0
0
$val;
8184
}
8185
}
8186
8187
sub seconds_to_hms {
8188
0
0
0
0
my ($self, $s) = @_;
8189
0
0
my $sign = 1;
8190
8191
0
0
0
if ($s < 0) {
8192
0
0
$sign = -1;
8193
0
0
$s = -$s;
8194
}
8195
8196
0
0
my $h = int($s / 3600);
8197
0
0
my $m = int(($s - $h * 3600) / 60);
8198
8199
0
0
$s -= $h * 3600 + $m * 60;
8200
8201
0
0
0
my $hms = sprintf('%s%uh%um%g', $sign < 0 ? '-' : '', $h, $m, $s);
8202
8203
0
0
0
$hms =~ s/\./s/ or $hms .= 's';
8204
0
0
$hms;
8205
}
8206
8207
sub drop_developer_data {
8208
0
0
0
0
my $self = shift;
8209
0
0
0
if (@_) {
8210
0
0
$self->{drop_developer_data} = $_[0];
8211
} else {
8212
0
0
$self->{drop_developer_data};
8213
}
8214
}
8215
8216
sub initialize {
8217
3
3
0
6
my $self = shift;
8218
3
7
my $buffer = '';
8219
8220
3
47
%$self = (
8221
'error' => undef,
8222
'file_read' => 0,
8223
'file_processed' => 0,
8224
'offset' => 0,
8225
'buffer' => \$buffer,
8226
'FH' => new FileHandle,
8227
'data_message_callback' => +{},
8228
'unit_table' => +{},
8229
'drop_developer_data' => 0,
8230
);
8231
8232
3
211
$self->data_message_callback_by_name(developer_data_id => \&syscallback_devdata_id);
8233
3
11
$self->data_message_callback_by_name(field_description => \&syscallback_devdata_field_desc);
8234
3
832
$self;
8235
}
8236
8237
# undocumented (used by fitdump.pl is chained files)
8238
sub reset {
8239
0
0
0
0
my $self = shift;
8240
0
0
$self->clear_buffer;
8241
8242
0
0
%$self = map {($_ => $self->{$_})} qw(error buffer FH data_message_callback unit_table profile_version
0
0
8243
cp_fit cp_fit_FH EOF use_gmtime numeric_date_time without_unit maybe_chained);
8244
8245
0
0
my $buffer = $self->buffer;
8246
0
0
$self->file_read(length($$buffer));
8247
0
0
$self->file_processed(0);
8248
0
0
$self;
8249
}
8250
8251
my @type_name = ();
8252
8253
$type_name[FIT_ENUM] = 'ENUM';
8254
$type_name[FIT_SINT8] = 'SINT8';
8255
$type_name[FIT_UINT8] = 'UINT8';
8256
$type_name[FIT_SINT16] = 'SINT16';
8257
$type_name[FIT_UINT16] = 'UINT16';
8258
$type_name[FIT_SINT32] = 'SINT32';
8259
$type_name[FIT_UINT32] = 'UINT32';
8260
$type_name[FIT_STRING] = 'STRING';
8261
$type_name[FIT_FLOAT32] = 'FLOAT32';
8262
$type_name[FIT_FLOAT64] = 'FLOAT64';
8263
$type_name[FIT_UINT8Z] = 'UINT8Z';
8264
$type_name[FIT_UINT16Z] = 'UINT16Z';
8265
$type_name[FIT_UINT32Z] = 'UINT32Z';
8266
$type_name[FIT_BYTE] = 'BYTE';
8267
8268
sub isnan {
8269
0
0
0
0
my $ret_val;
8270
6
6
317572
do { no warnings 'numeric'; $ret_val = !defined( $_[0] <=> 9**9**9 ) };
6
14
6
17982
0
0
0
0
8271
0
0
return $ret_val
8272
}
8273
8274
sub print_all_fields {
8275
0
0
0
0
my ($self, $desc, $v, %opt) = @_;
8276
0
0
my ($indent, $FH, $skip_invalid) = @opt{qw(indent FH skip_invalid)};
8277
8278
0
0
0
$FH=\*STDOUT if !defined $FH;
8279
0
0
0
$FH->print($indent, 'compressed_timestamp: ', $self->named_type_value('date_time', $v->[$#$v]), "\n") if $desc->{array_length} == $#$v;
8280
8281
0
0
for my $i_name (sort {$desc->{$a} <=> $desc->{$b}} grep {/^i_/} keys %$desc) {
0
0
0
0
8282
0
0
my $name = $i_name;
8283
0
0
$name =~ s/^i_//;
8284
8285
0
0
my $attr = $desc->{'a_' . $name};
8286
0
0
my $tname = $desc->{'t_' . $name};
8287
0
0
my $pname = $name;
8288
8289
0
0
0
if (ref $attr->{switch} eq 'HASH') {
8290
0
0
my $t_attr = $self->switched($desc, $v, $attr->{switch});
8291
8292
0
0
0
if (ref $t_attr eq 'HASH') {
8293
0
0
$attr = $t_attr;
8294
0
0
$tname = $attr->{type_name};
8295
0
0
$pname = $attr->{name};
8296
}
8297
}
8298
8299
0
0
my $i = $desc->{$i_name};
8300
0
0
my $c = $desc->{'c_' . $name};
8301
0
0
my $type = $desc->{'T_' . $name};
8302
0
0
my $invalid = $desc->{'I_' . $name};
8303
0
0
my $j;
8304
8305
0
0
for ($j = 0 ; $j < $c ; ++$j) {
8306
0
0
0
isnan($v->[$i + $j]) && next;
8307
0
0
0
$v->[$i + $j] != $invalid && last;
8308
}
8309
8310
0
0
0
0
if ($j < $c || !$skip_invalid) {
8311
0
0
0
0
$self->last_timestamp($v->[$i]) if $type == FIT_UINT32 && $tname eq 'date_time' && $pname eq 'timestamp';
0
8312
0
0
0
$FH->print($indent, $pname, ' (', $desc->{'N_' . $name}, '-', $c, '-', $type_name[$type] ne '' ? $type_name[$type] : $type);
8313
0
0
0
$FH->print(', original name: ', $name) if $name ne $pname;
8314
0
0
0
$FH->print(', INVALID') if $j >= $c;
8315
0
0
$FH->print('): ');
8316
8317
0
0
0
if ($type == FIT_STRING) {
8318
0
0
$FH->print("\"", $self->string_value($v, $i, $c), "\"\n");
8319
} else {
8320
0
0
0
$FH->print('{') if $c > 1;
8321
8322
0
0
my $pval = $self->value_cooked($tname, $attr, $invalid, $v->[$i]);
8323
8324
0
0
$FH->print($pval);
8325
0
0
0
$FH->print(' (', $v->[$i], ')') if $v->[$i] ne $pval;
8326
8327
0
0
0
if ($c > 1) {
8328
0
0
my ($j, $k);
8329
8330
0
0
for ($j = $i + 1, $k = $i + $c ; $j < $k ; ++$j) {
8331
0
0
$pval = $self->value_cooked($tname, $attr, $invalid, $v->[$j]);
8332
0
0
$FH->print(', ', $pval);
8333
0
0
0
$FH->print(' (', $v->[$j], ')') if $v->[$j] ne $pval;
8334
}
8335
0
0
$FH->print('}');
8336
}
8337
0
0
$FH->print("\n");
8338
}
8339
}
8340
}
8341
0
0
1;
8342
}
8343
8344
sub print_all_json {
8345
0
0
0
0
my ($self, $desc, $v, %opt) = @_;
8346
0
0
my ($indent, $FH, $skip_invalid) = @opt{qw(indent FH skip_invalid)};
8347
8348
0
0
my $out = 0;
8349
8350
0
0
0
$FH=\*STDOUT if !defined $FH;
8351
0
0
0
if ($desc->{array_length} == $#$v) {
8352
0
0
$FH->print($indent, '"compressed_timestamp": "', $self->named_type_value('date_time', $v->[$#$v]), '"');
8353
0
0
$out = $out + 1;
8354
}
8355
8356
0
0
for my $i_name (sort {$desc->{$a} <=> $desc->{$b}} grep {/^i_/} keys %$desc) {
0
0
0
0
8357
0
0
my $name = $i_name;
8358
0
0
$name =~ s/^i_//;
8359
8360
0
0
my $attr = $desc->{'a_' . $name};
8361
0
0
my $tname = $desc->{'t_' . $name};
8362
0
0
my $pname = $name;
8363
8364
0
0
0
if (ref $attr->{switch} eq 'HASH') {
8365
0
0
my $t_attr = $self->switched($desc, $v, $attr->{switch});
8366
8367
0
0
0
if (ref $t_attr eq 'HASH') {
8368
0
0
$attr = $t_attr;
8369
0
0
$tname = $attr->{type_name};
8370
0
0
$pname = $attr->{name};
8371
}
8372
}
8373
8374
0
0
my $i = $desc->{$i_name};
8375
0
0
my $c = $desc->{'c_' . $name};
8376
0
0
my $type = $desc->{'T_' . $name};
8377
0
0
my $invalid = $desc->{'I_' . $name};
8378
0
0
my $j;
8379
8380
0
0
for ($j = 0 ; $j < $c ; ++$j) {
8381
0
0
0
isnan($v->[$i + $j]) && next;
8382
0
0
0
$v->[$i + $j] != $invalid && last;
8383
}
8384
8385
0
0
0
0
if ($j < $c || !$skip_invalid) {
8386
0
0
0
0
$self->last_timestamp($v->[$i]) if $type == FIT_UINT32 && $tname eq 'date_time' && $pname eq 'timestamp';
0
8387
0
0
0
$FH->print(",\n") if $out;
8388
0
0
$FH->print($indent, '"', $pname, '": ');
8389
8390
0
0
0
if ($type == FIT_STRING) {
8391
0
0
$FH->print("\"", $self->string_value($v, $i, $c), "\"");
8392
} else {
8393
0
0
0
$FH->print('[') if $c > 1;
8394
8395
0
0
my $pval = $self->value_cooked($tname, $attr, $invalid, $v->[$i]);
8396
8397
0
0
0
if (looks_like_number($pval)) {
8398
0
0
$FH->print($pval);
8399
} else {
8400
0
0
$FH->print("\"$pval\"");
8401
}
8402
8403
0
0
0
if ($c > 1) {
8404
0
0
my ($j, $k);
8405
8406
0
0
for ($j = $i + 1, $k = $i + $c ; $j < $k ; ++$j) {
8407
0
0
$pval = $self->value_cooked($tname, $attr, $invalid, $v->[$j]);
8408
0
0
$FH->print(', ');
8409
0
0
0
if (looks_like_number($pval)) {
8410
0
0
$FH->print($pval);
8411
} else {
8412
0
0
$FH->print("\"$pval\"");
8413
}
8414
}
8415
8416
0
0
$FH->print(']');
8417
}
8418
}
8419
0
0
$out = $out + 1;
8420
}
8421
}
8422
0
0
1;
8423
}
8424
8425
=over 4
8426
8427
=item use_gmtime(I)
8428
8429
sets the flag which of GMT or local timezone is used for C type value conversion.
8430
8431
=back
8432
8433
=cut
8434
8435
my $use_gmtime = 0;
8436
8437
sub use_gmtime {
8438
0
0
1
0
my $self = shift;
8439
8440
0
0
0
if (@_) {
0
8441
0
0
0
if (ref $self eq '') {
8442
0
0
$use_gmtime = $_[0];
8443
} else {
8444
0
0
$self->{use_gmtime} = $_[0];
8445
}
8446
} elsif (ref $self eq '') {
8447
0
0
$use_gmtime;
8448
} else {
8449
0
0
$self->{use_gmtime};
8450
}
8451
}
8452
8453
=over 4
8454
8455
=item unit_table(I => I)
8456
8457
sets I for I.
8458
8459
=back
8460
8461
=cut
8462
8463
sub unit_table {
8464
0
0
1
0
my $self = shift;
8465
0
0
my $unit = shift;
8466
8467
0
0
0
if (@_) {
8468
0
0
$self->{unit_table}->{$unit} = $_[0];
8469
} else {
8470
0
0
$self->{unit_table}->{$unit};
8471
}
8472
}
8473
8474
sub without_unit {
8475
0
0
0
0
my $self = shift;
8476
0
0
0
if (@_) {
8477
0
0
$self->{without_unit} = $_[0];
8478
} else {
8479
0
0
$self->{without_unit};
8480
}
8481
}
8482
8483
=over 4
8484
8485
=item semicircles_to_degree(I)
8486
8487
=item mps_to_kph(I)
8488
8489
wrapper methods of C method.
8490
8491
=back
8492
8493
=cut
8494
8495
sub semicircles_to_degree {
8496
0
0
1
0
my ($self, $on) = @_;
8497
0
0
0
$self->unit_table('semicircles' => $on ? +{'unit' => 'deg', 'scale' => 2 ** 31 / 180} : undef);
8498
}
8499
8500
sub mps_to_kph {
8501
0
0
1
0
my ($self, $on) = @_;
8502
0
0
0
$self->unit_table('m/s' => $on ? +{'unit' => 'km/h', 'scale' => 1 / 3.6} : undef);
8503
}
8504
8505
=over 4
8506
8507
=item close()
8508
8509
closes opened file handles.
8510
8511
=back
8512
8513
=cut
8514
8515
sub close {
8516
3
3
1
1228
my $self = shift;
8517
3
12
my $cp_fit_FH = $self->cp_fit_FH;
8518
3
8
my $FH = $self->FH;
8519
8520
3
50
33
12
$cp_fit_FH->close if &safe_isa($cp_fit_FH, 'FileHandle') && $cp_fit_FH->opened;
8521
3
50
30
$FH->close if $FH->opened;
8522
}
8523
8524
=over 4
8525
8526
=item profile_version_string()
8527
8528
Returns a string representation of the profile version used by the device or application that created the FIT file opened in the instance.
8529
8530
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.
8531
8532
=back
8533
8534
=head2 Constants
8535
8536
Following constants are exported: C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C.
8537
8538
Also exported are:
8539
8540
=over 4
8541
8542
=item FIT_BYTE
8543
8544
numbers representing base types of field values in data messages.
8545
8546
=item FIT_BASE_TYPE_MAX
8547
8548
the maximal number representing base types of field values in data messages.
8549
8550
=item FIT_HEADER_LENGTH
8551
8552
length of a .FIT file header.
8553
8554
=back
8555
8556
=head2 Data message descriptor
8557
8558
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.
8559
8560
=over 4
8561
8562
=item I => I
8563
8564
in a global .FIT profile.
8565
8566
=item C => I
8567
8568
necessarily.
8569
8570
=item C => I
8571
8572
necessarily.
8573
8574
=item C => I
8575
8576
only if the message is documented.
8577
8578
=item C => I
8579
8580
of a callback function and callback data, only if a C is registered.
8581
8582
=item C => I
8583
8584
of multi-octets data in this message, where 0 for littel-endian and 1 for big-endian.
8585
8586
=item C => I
8587
8588
used to convert the binary data to an array of Perl representations.
8589
8590
=item CI => I
8591
8592
of the value(s) of the field named I.
8593
8594
=item CI => I
8595
8596
of the value(s) of the field named I.
8597
8598
=item CI => I
8599
8600
of the field named I.
8601
8602
=item CI => I
8603
8604
of whole the field named I in binary data.
8605
8606
=item CI => I
8607
8608
of attributes of the field named I.
8609
8610
=item CI => I
8611
8612
only if the type of the value of the field named I has a name.
8613
8614
=item CI => I
8615
8616
representing base type of the value of the field named I.
8617
8618
=item CI => I
8619
8620
representing index of the filed named I in the global .FIT profile.
8621
8622
=item CI => I
8623
8624
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.
8625
8626
=item C => I
8627
8628
used for endian conversion.
8629
8630
=item C => I
8631
8632
in octets.
8633
8634
=item C => I
8635
8636
of Perl representations.
8637
8638
=back
8639
8640
=head2 Callback function
8641
8642
When C method meets a data message, it calls a I registered with C or C,
8643
in the form
8644
8645
=over 4
8646
8647
=item I-E(I, I, I, I, ...).
8648
8649
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.
8650
8651
=back
8652
8653
=head2 Developer data
8654
8655
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.
8656
8657
Each I is made from the value of C field in the corresponding I, after the following conversion rules:
8658
8659
=over 4
8660
8661
=item (1) Each sequence of space characters is converted to single C<_>.
8662
8663
=item (2) Each of remaining non-word-constituend characters is converted to C<_> + 2 column hex representation of C of the character + C<_>.
8664
8665
=back
8666
8667
=head2 64bit data
8668
8669
If your perl lacks 64bit integer support, you need the module C.
8670
8671
=head1 DEPENDENCIES
8672
8673
Nothing in particular so far.
8674
8675
=head1 SEE ALSO
8676
8677
L, L, L, L, L.
8678
8679
=head1 BUGS AND LIMITATIONS
8680
8681
No bugs have been reported.
8682
8683
Please report any bugs or feature requests to C, or through the web interface at L.
8684
8685
=head1 AUTHOR
8686
8687
Originally written by Kiyokazu Suto C<< suto@ks-and-ks.ne.jp >> with contributions by Matjaz Rihtar.
8688
8689
This version is maintained by Patrick Joly C<< >>.
8690
8691
Please visit the project page at: L.
8692
8693
=head1 VERSION
8694
8695
1.07
8696
8697
=head1 LICENSE AND COPYRIGHT
8698
8699
Copyright 2022, Patrick Joly C<< patjol@cpan.org >>. All rights reserved.
8700
8701
Copyright 2016-2022, Kiyokazu Suto C<< suto@ks-and-ks.ne.jp >>. All rights reserved.
8702
8703
This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See L.
8704
8705
=head1 DISCLAIMER OF WARRANTY
8706
8707
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.
8708
8709
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.
8710
8711
=cut
8712
8713
1;
8714