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