Skip to content
This repository was archived by the owner on May 8, 2025. It is now read-only.

Commit 3581628

Browse files
Merge pull request #38 from adriangibbons/dev
Some updates from FIT v2.2
2 parents 8112481 + 014c5de commit 3581628

File tree

1 file changed

+153
-6
lines changed

1 file changed

+153
-6
lines changed

src/phpFITFileAnalysis.php

Lines changed: 153 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ class phpFITFileAnalysis
393393
1497 => 'Edge 800', // 'edge800_korea',
394394
1499 => 'swim',
395395
1537 => 'Forerunner 910XT', // 'fr910xt_china',
396-
1551 => 'fenix',
396+
1551 => 'Fenix', // fenix
397397
1555 => 'edge200_taiwan',
398398
1561 => 'Edge 510', // 'edge510',
399399
1567 => 'Edge 810', // 'edge810',
@@ -421,12 +421,70 @@ class phpFITFileAnalysis
421421
1929 => 'Forerunner 620', // 'fr620_china',
422422
1930 => 'Forerunner 220', // 'fr220_japan',
423423
1931 => 'Forerunner 220', // 'fr220_china',
424-
1967 => 'fenix2',
425-
10007 => 'sdm4',
424+
1967 => 'Fenix 2', // fenix2
425+
1988 => 'epix',
426+
2050 => 'Fenix 3', // fenix3
427+
2052 => 'Edge 1000', // edge1000_taiwan
428+
2053 => 'Edge 1000', // edge1000_japan
429+
2061 => 'Forerunner 15', // fr15_japan
430+
2067 => 'Edge 520', // edge520
431+
2070 => 'Edge 1000', // edge1000_china
432+
2072 => 'Forerunner 620', // fr620_russia
433+
2073 => 'Forerunner 220', // fr220_russia
434+
2079 => 'vector_s',
435+
2100 => 'Edge 1000', // edge1000_korea
436+
2130 => 'Forerunner 920', // fr920xt_taiwan
437+
2131 => 'Forerunner 920', // fr920xt_china
438+
2132 => 'Forerunner 920', // fr920xt_japan
439+
2134 => 'virbx',
440+
2135 => 'vivo_smart_apac',
441+
2140 => 'etrex_touch',
442+
2147 => 'Edge 25', // edge25
443+
2148 => 'Forerunner 25', // fr25
444+
2150 => 'vivo_fit2',
445+
2153 => 'Forerunner 225', // fr225
446+
2156 => 'Forerunner 630', // fr630
447+
2157 => 'Forerunner 230', // fr230
448+
2160 => 'vivo_active_apac',
449+
2161 => 'vector_2',
450+
2162 => 'vector_2s',
451+
2172 => 'virbxe',
452+
2173 => 'Forerunner 620', // fr620_taiwan
453+
2174 => 'Forerunner 220', // fr220_taiwan
454+
2175 => 'truswing',
455+
2188 => 'Fenix 3', // fenix3_china
456+
2189 => 'Fenix 3', // fenix3_twn
457+
2192 => 'varia_headlight',
458+
2193 => 'varia_taillight_old',
459+
2204 => 'Edge Explore 1000', // edge_explore_1000
460+
2219 => 'Forerunner 225', // fr225_asia
461+
2225 => 'varia_radar_taillight',
462+
2226 => 'varia_radar_display',
463+
2238 => 'Edge 20', // edge20
464+
2262 => 'd2_bravo',
465+
2266 => 'approach_s20',
466+
2276 => 'varia_remote',
467+
2327 => 'hrm4_run',
468+
2337 => 'vivo_active_hr',
469+
2347 => 'vivo_smart_gps_hr',
470+
2348 => 'vivo_smart_hr',
471+
2368 => 'vivo_move',
472+
2398 => 'varia_vision',
473+
2406 => 'vivo_fit3',
474+
2413 => 'Fenix 3 HR', // fenix3_hr
475+
2429 => 'index_smart_scale',
476+
2431 => 'Forerunner 235', // fr235
477+
2441 => 'oregon7xx',
478+
2444 => 'rino7xx',
479+
2496 => 'nautix',
480+
2530 => 'Edge 820', // edge_820
481+
2531 => 'Edge Explore 820', // edge_explore_820
482+
10007 => 'SDM4 footpod', // sdm4
426483
10014 => 'edge_remote',
427484
20119 => 'training_center',
485+
65531 => 'connectiq_simulator',
428486
65532 => 'android_antplus_plugin',
429-
65534 => 'connect'
487+
65534 => 'Garmin Connect website' // connect
430488
],
431489
'sport' => [ // Have capitalised and replaced underscores with spaces.
432490
0 => 'Generic',
@@ -496,7 +554,7 @@ class phpFITFileAnalysis
496554
];
497555

498556
/**
499-
* D00001275 Flexible & Interoperable Data Transfer (FIT) Protocol Rev 1.7.pdf
557+
* D00001275 Flexible & Interoperable Data Transfer (FIT) Protocol Rev 2.2.pdf
500558
* Table 4-6. FIT Base Types and Invalid Values
501559
*
502560
* $types array holds a string used by the PHP unpack() function to format binary data.
@@ -518,6 +576,9 @@ class phpFITFileAnalysis
518576
139 => 'vtmp', // uint16z
519577
140 => 'Vtmp', // uint32z
520578
13 => 'Ctmp', // byte
579+
142 => 'Ptmp', // sint64 - manually convert uint64 to sint64 in fixData()
580+
143 => 'Ptmp', // uint64
581+
144 => 'Ptmp' // uint64z
521582
],
522583
1 => [ // Big Endianness
523584
0 => 'Ctmp', // enum
@@ -534,6 +595,9 @@ class phpFITFileAnalysis
534595
139 => 'ntmp', // uint16z
535596
140 => 'Ntmp', // uint32z
536597
13 => 'Ctmp', // byte
598+
142 => 'Jtmp', // sint64 - manually convert uint64 to sint64 in fixData()
599+
143 => 'Jtmp', // uint64
600+
144 => 'Jtmp' // uint64z
537601
]
538602
];
539603

@@ -552,6 +616,9 @@ class phpFITFileAnalysis
552616
139 => 0, // 0x0000
553617
140 => 0, // 0x00000000
554618
13 => 255, // 0xFF
619+
142 => 9223372036854775807, // 0x7FFFFFFFFFFFFFFF
620+
143 => 18446744073709551615, // 0xFFFFFFFFFFFFFFFF
621+
144 => 0 // 0x0000000000000000
555622
];
556623

557624
/**
@@ -931,6 +998,35 @@ class phpFITFileAnalysis
931998
253 => ['field_name' => 'timestamp', 'scale' => 1, 'offset' => 0, 'units' => 's'],
932999
254 => ['field_name' => 'message_index', 'scale' => 1, 'offset' => 0, 'units' => '']
9331000
]
1001+
],
1002+
1003+
206 => [
1004+
'mesg_name' => 'field_description', 'field_defns' => [
1005+
0 => ['field_name' => 'developer_data_index', 'scale' => 1, 'offset' => 0, 'units' => ''],
1006+
1 => ['field_name' => 'field_definition_number', 'scale' => 1, 'offset' => 0, 'units' => ''],
1007+
2 => ['field_name' => 'fit_base_type_id', 'scale' => 1, 'offset' => 0, 'units' => ''],
1008+
3 => ['field_name' => 'field_name', 'scale' => 1, 'offset' => 0, 'units' => ''],
1009+
4 => ['field_name' => 'array', 'scale' => 1, 'offset' => 0, 'units' => ''],
1010+
5 => ['field_name' => 'components', 'scale' => 1, 'offset' => 0, 'units' => ''],
1011+
6 => ['field_name' => 'scale', 'scale' => 1, 'offset' => 0, 'units' => ''],
1012+
7 => ['field_name' => 'offset', 'scale' => 1, 'offset' => 0, 'units' => ''],
1013+
8 => ['field_name' => 'units', 'scale' => 1, 'offset' => 0, 'units' => ''],
1014+
9 => ['field_name' => 'bits', 'scale' => 1, 'offset' => 0, 'units' => ''],
1015+
10 => ['field_name' => 'accumulate', 'scale' => 1, 'offset' => 0, 'units' => ''],
1016+
13 => ['field_name' => 'fit_base_unit_id', 'scale' => 1, 'offset' => 0, 'units' => ''],
1017+
14 => ['field_name' => 'native_mesg_num', 'scale' => 1, 'offset' => 0, 'units' => ''],
1018+
15 => ['field_name' => 'native_field_num', 'scale' => 1, 'offset' => 0, 'units' => '']
1019+
]
1020+
],
1021+
1022+
207 => [
1023+
'mesg_name' => 'developer_data_id', 'field_defns' => [
1024+
0 => ['field_name' => 'developer_id', 'scale' => 1, 'offset' => 0, 'units' => ''],
1025+
1 => ['field_name' => 'application_id', 'scale' => 1, 'offset' => 0, 'units' => ''],
1026+
2 => ['field_name' => 'manufacturer_id', 'scale' => 1, 'offset' => 0, 'units' => ''],
1027+
3 => ['field_name' => 'developer_data_index', 'scale' => 1, 'offset' => 0, 'units' => ''],
1028+
4 => ['field_name' => 'application_version', 'scale' => 1, 'offset' => 0, 'units' => '']
1029+
]
9341030
]
9351031
];
9361032

@@ -1009,20 +1105,22 @@ private function readDataRecords()
10091105
{
10101106
$record_header_byte = 0;
10111107
$message_type = 0;
1108+
$developer_data_flag = 0;
10121109
$local_mesg_type = 0;
10131110

10141111
while ($this->file_header['header_size'] + $this->file_header['data_size'] > $this->file_pointer) {
10151112
$record_header_byte = ord(substr($this->file_contents, $this->file_pointer, 1));
10161113
$this->file_pointer++;
10171114

10181115
/**
1019-
* D00001275 Flexible & Interoperable Data Transfer (FIT) Protocol Rev 1.7.pdf
1116+
* D00001275 Flexible & Interoperable Data Transfer (FIT) Protocol Rev 2.2.pdf
10201117
* Table 4-1. Normal Header Bit Field Description
10211118
*/
10221119
if (($record_header_byte >> 7) & 1) { // Check that it's a normal header
10231120
throw new \Exception('phpFITFileAnalysis->readDataRecords(): this class can only handle normal headers!');
10241121
}
10251122
$message_type = ($record_header_byte >> 6) & 1; // 1: DEFINITION_MESSAGE; 0: DATA_MESSAGE
1123+
$developer_data_flag = ($record_header_byte >> 5) & 1; // 1: DEFINITION_MESSAGE; 0: DATA_MESSAGE
10261124
$local_mesg_type = $record_header_byte & 15; // bindec('1111') == 15
10271125

10281126
switch ($message_type) {
@@ -1058,16 +1156,39 @@ private function readDataRecords()
10581156
$total_size += $size;
10591157
}
10601158

1159+
$num_dev_fields = 0;
1160+
$dev_field_definitions = [];
1161+
if ($developer_data_flag === 1) {
1162+
$num_dev_fields = ord(substr($this->file_contents, $this->file_pointer, 1));
1163+
$this->file_pointer++;
1164+
1165+
for ($i=0; $i<$num_dev_fields; ++$i) {
1166+
$field_definition_number = ord(substr($this->file_contents, $this->file_pointer, 1));
1167+
$this->file_pointer++;
1168+
$size = ord(substr($this->file_contents, $this->file_pointer, 1));
1169+
$this->file_pointer++;
1170+
$developer_data_index = ord(substr($this->file_contents, $this->file_pointer, 1));
1171+
$this->file_pointer++;
1172+
1173+
$dev_field_definitions[] = ['field_definition_number' => $field_definition_number, 'size' => $size, 'developer_data_index' => $developer_data_index];
1174+
$total_size += $size;
1175+
}
1176+
}
1177+
10611178
$this->defn_mesgs[$local_mesg_type] = [
10621179
'global_mesg_num' => $global_mesg_num,
10631180
'num_fields' => $num_fields,
10641181
'field_defns' => $field_definitions,
1182+
'num_dev_fields' => $num_dev_fields,
1183+
'dev_field_definitions' => $dev_field_definitions,
10651184
'total_size' => $total_size
10661185
];
10671186
$this->defn_mesgs_all[] = [
10681187
'global_mesg_num' => $global_mesg_num,
10691188
'num_fields' => $num_fields,
10701189
'field_defns' => $field_definitions,
1190+
'num_dev_fields' => $num_dev_fields,
1191+
'dev_field_definitions' => $dev_field_definitions,
10711192
'total_size' => $total_size
10721193
];
10731194
break;
@@ -1104,6 +1225,11 @@ private function readDataRecords()
11041225
$this->file_pointer += $field_defn['size'];
11051226
}
11061227

1228+
// TODO: process Developer Data correctly - just skipping over it at the moment
1229+
foreach ($this->defn_mesgs[$local_mesg_type]['dev_field_definitions'] as $field_defn) {
1230+
$this->file_pointer += $field_defn['size'];
1231+
}
1232+
11071233
// Process the temporary array and load values into the public data messages array
11081234
if (!empty($tmp_record_array)) {
11091235
$timestamp = isset($this->data_mesgs['record']['timestamp']) ? max($this->data_mesgs['record']['timestamp']) + 1 : 0;
@@ -1178,6 +1304,7 @@ private function fixData($options)
11781304
// http://php.net/manual/en/function.pack.php - signed integers endianness is always machine dependent.
11791305
// 131 s signed short (always 16 bit, machine byte order)
11801306
// 133 l signed long (always 32 bit, machine byte order)
1307+
// 142 q signed long long (always 64 bit, machine byte order)
11811308
foreach ($this->defn_mesgs_all as $mesg) {
11821309
if (isset($this->data_mesg_info[$mesg['global_mesg_num']])) {
11831310
$mesg_name = $this->data_mesg_info[$mesg['global_mesg_num']]['mesg_name'];
@@ -1223,6 +1350,26 @@ private function fixData($options)
12231350
$this->data_mesgs[$mesg_name][$field_name] = -1 * ($this->data_mesgs[$mesg_name][$field_name] - 0x7FFFFFFF);
12241351
}
12251352
}
1353+
} // Convert uint64 to sint64
1354+
elseif ($field['base_type'] === 142 && isset($this->data_mesg_info[$mesg['global_mesg_num']]['field_defns'][$field['field_definition_number']]['field_name'])) {
1355+
$field_name = $this->data_mesg_info[$mesg['global_mesg_num']]['field_defns'][$field['field_definition_number']]['field_name'];
1356+
if (isset($this->data_mesgs[$mesg_name][$field_name])) {
1357+
if (is_array($this->data_mesgs[$mesg_name][$field_name])) {
1358+
foreach ($this->data_mesgs[$mesg_name][$field_name] as &$v) {
1359+
if (PHP_INT_SIZE === 8 && $v > 0x7FFFFFFFFFFFFFFF) {
1360+
$v -= 0x10000000000000000;
1361+
}
1362+
if ($v > 0x7FFFFFFFFFFFFFFF) {
1363+
$v = -1 * ($v - 0x7FFFFFFFFFFFFFFF);
1364+
}
1365+
}
1366+
} elseif ($this->data_mesgs[$mesg_name][$field_name] > 0x7FFFFFFFFFFFFFFF) {
1367+
if (PHP_INT_SIZE === 8) {
1368+
$this->data_mesgs[$mesg_name][$field_name] -= 0x10000000000000000;
1369+
}
1370+
$this->data_mesgs[$mesg_name][$field_name] = -1 * ($this->data_mesgs[$mesg_name][$field_name] - 0x7FFFFFFFFFFFFFFF);
1371+
}
1372+
}
12261373
}
12271374
}
12281375
}

0 commit comments

Comments
 (0)