adriangibbons / php-fit-file-analysis
用于分析由Garmin GPS设备创建的FIT文件的PHP类
Requires (Dev)
- phpunit/phpunit: 4.8.*
- satooshi/php-coveralls: ^2.0
- squizlabs/php_codesniffer: 2.*
README
phpFITFileAnalysis
用于分析由Garmin GPS设备创建的FIT文件的PHP类(≥v5.4)。
实时演示(右键单击并在新标签页中打开)
演示截图
如果您有任何问题或需要支持,请首先阅读本页的全部内容和常见问题解答(FAQ)。
什么是FIT文件?
FIT或灵活和互操作数据传输是一种用于GPS轨迹和路线的文件格式。它被较新的Garmin健身GPS设备使用,包括Edge和Forerunner系列,这些设备在自行车和跑步者中很受欢迎。
访问Wiki中的常见问题解答页面以获取更多信息。
我如何使用phpFITFileAnalysis与我的PHP网站一起使用?
这里有几个选择
更现代的方法:在composer.json文件中添加包adriangibbons/php-fit-file-analysis
{ "require": { "adriangibbons/php-fit-file-analysis": "^3.2.0" } }
从命令行运行composer update
。
composer.json文件应该自动加载phpFITFileAnalysis
类,因此只要你在PHP文件中包含自动加载文件,你应该能够使用以下方式实例化该类:
<?php require __DIR__ . '/vendor/autoload.php'; // this file is in the project's root folder $pFFA = new adriangibbons\phpFITFileAnalysis('fit_files/my_fit_file.fit'); ?>
更手动的方法:从GitHub下载ZIP文件,并将来自/src目录的PHP类文件放在适当的位置(例如classes/)。已经尽力将所有内容保持在一个文件中。
然后在您想要使用的PHP页面上包含该文件,并实例化该类的对象
<?php include('classes/phpFITFileAnalysis.php'); $pFFA = new adriangibbons\phpFITFileAnalysis('fit_files/my_fit_file.fit'); ?>
请注意,在创建实例时,所需的唯一强制参数是要加载的FIT文件的路径。
还有更多可提供的可选参数。这些将在本页下方进行更详细的描述。
该对象将自动加载FIT文件并遍历其内容。它将找到的任何数据存储在数组中,这些数组可通过公共数据变量访问。
访问数据
由类读取的数据存储在关联数组中,这些数组可通过公共数据变量访问
$pFFA->data_mesgs
数组索引是消息和它们包含的字段的名称。例如
// Contains an array of all heart_rate data read from the file, indexed by timestamp $pFFA->data_mesgs['record']['heart_rate'] // Contains an integer identifying the number of laps $pFFA->data_mesgs['session']['num_laps']
但是,我如何知道我的文件中有哪些消息和字段?您可以通过迭代$pFFA->data_mesgs数组或查看可以转储到网页上的调试信息来做到这一点
// Option 1. Iterate through the $pFFA->data_mesgs array foreach ($pFFA->data_mesgs as $mesg_key => $mesg) { // Iterate the array and output the messages echo "<strong>Found Message: $mesg_key</strong><br>"; foreach ($mesg as $field_key => $field) { // Iterate each message and output the fields echo " - Found Field: $mesg_key -> $field_key<br>"; } echo "<br>"; } // Option 2. Show the debug information $pFFA->showDebugInfo(); // Quite a lot of info...
有没有一些实际示例?
// Get Max and Avg Speed echo "Maximum Speed: ".max($pFFA->data_mesgs['record']['speed'])."<br>"; echo "Average Speed: ".( array_sum($pFFA->data_mesgs['record']['speed']) / count($pFFA->data_mesgs['record']['speed']) )."<br>"; // Put HR data into a JavaScript array for use in a Chart echo "var chartData = ["; foreach ($pFFA->data_mesgs['record']['heart_rate'] as $timestamp => $hr_value) { echo "[$timestamp,$hr_value],"; } echo "];";
枚举数据 FIT协议使用了枚举数据类型。在FIT SDK中识别了这些值后,它们已作为私有变量包含在类中:$enum_data。
有一个公共函数可以返回给定消息类型的枚举值。例如
// Access data stored within the private class variable $enum_data // $pFFA->enumData($type, $value) // e.g. echo $pFFA->enumData('sport', 2)); // returns 'cycling' echo $pFFA->enumData('manufacturer', $this->data_mesgs['device_info']['manufacturer']); // returns 'Garmin'; echo $pFFA->manufacturer(); // Short-hand for above
此外,公共函数还提供了访问常用枚举数据的简写方法
- manufacturer()
- product()
- sport()
可选参数
当实例化phpFITFileAnalysis对象时,可以传递五个可选参数作为关联数组。这些是
- fix_data
- 每秒数据
- 单位
- 配速
- garmin时间戳
- 用开发数据覆盖
例如
$options = [ 'fix_data' => ['cadence', 'distance'], 'data_every_second' => true 'units' => 'statute', 'pace' => true, 'garmin_timestamps' => true, 'overwrite_with_dev_data' => false ]; $pFFA = new adriangibbons\phpFITFileAnalysis('my_fit_file.fit', $options);
可选参数的详细信息如下所述。
“修复”数据
观察到的FIT文件中,一些数据点缺失了一个传感器(例如踏频/足部感应器),而其他传感器(例如心率)在同一时刻收集了信息。原因未知,通常只有相对少量的数据点缺失。修复问题可能是多余的,因为每个数据项都使用时间戳进行索引。然而,对于您的项目来说,每种类型的数据点数量完全相同可能很重要。
识别的值: 'all', 'cadence', 'distance', 'heart_rate', 'lat_lon', 'power', 'speed'
**示例:**
$options = ['fix_data' => ['all']]; // fix cadence, distance, heart_rate, lat_lon, power, and speed data $options = ['fix_data' => ['cadence', 'distance']]; // fix cadence and distance data only $options = ['fix_data' => ['lat_lon']]; // fix position data only
如果没有提供fix_data数组,则不执行数据的“修复”。
一个FIT文件可能包含以下内容
如上图所示,最易缺失数据点的数据类型是:位置纬度、位置经度、海拔、心率、踏频、距离、速度和功率。
除踏频信息外,缺失的数据点通过插入插值值来“修复”。
对于踏频,插入零,因为在这种情况下,很可能是因为在那一时刻没有运动而没有收集到数据。
缺失数据点的插值
// Do not use code, just for demonstration purposes var_dump($pFFA->data_mesgs['record']['temperature']); // ['100'=>22, '101'=>22, '102'=>23, '103'=>23, '104'=>23]; var_dump($pFFA->data_mesgs['record']['distance']); // ['100'=>3.62, '101'=>4.01, '104'=>10.88];
如上例所示,温度数据已记录在每个五个时间戳(100、101、102、103和104)上。然而,距离信息没有记录在时间戳102和103上。
如果fix_data包含'distance',则该类将尝试在索引102和103的距离数组中插入数据。值使用索引101(4.01)和104(10.88)之间的线性插值确定。
结果将是
var_dump($pFFA->data_mesgs['record']['distance']); // ['100'=>3.62, '101'=>4.01, '102'=>6.30, '103'=>8.59, '104'=>10.88];
每秒数据
一些Garmin的健身设备提供了智能录制或每秒录制的选项。
智能录制记录了健身设备改变方向、速度、心率或海拔的关键点。这种录制类型记录的轨迹点较少,可能存在大于一秒的时间戳间隙。
您可以通过设置选项强制时间戳为均匀的一秒间隔
$options = ['data_every_second' => true];
缺失的时间戳将根据上述fix_data
选项进行插值。
如果没有指定与data_every_second
一起的fix_data
选项,则假定'fix_data' => ['all']
。
请注意,您可能会在使用fix_data
选项时遇到性能下降。将探索提高性能的方法 - 很可能interpolateMissingData()
函数次优。
设置单位
默认情况下,假定使用以下表格中标识的公制单位。
您可以选择请求英制或原始单位,而不是公制。原始单位是创建FIT文件的设备使用的单位,并且是FIT标准的本地单位(即从文件中读取的值不会进行转换)。
要选择所需的单位,请使用以下选项之一
$options = ['units' => 'statute']; $options = ['units' => 'raw']; $options = ['units' => 'metric']; // explicit but not necessary, same as default
配速
如果用户需要,可以提供配速而不是速度。根据请求的单位,配速将以每公里分钟(min/km)的公制单位表示;或每英里分钟(min/mi)的英制单位表示。
要选择配速,请使用以下选项
$options = ['pace' => true];
配速值将是小数分钟。要获取秒数,您可能需要进行类似以下操作
foreach ($pFFA->data_mesgs['record']['speed'] as $key => $value) { $min = floor($value); $sec = round(60 * ($value - $min)); echo "pace: $min min $sec sec<br>"; }
请注意,如果请求的是原始单位,则此参数不会影响速度数据,因为它从文件中读取的值保持不变。
时间戳
Unix时间是从1970年1月1日UTC 00:00:00开始到现在的秒数,然而FIT标准指定时间戳(即date_time和local_date_time类型的字段)表示的是从1989年12月31日UTC 00:00:00开始的秒数。
FIT和Unix时间戳之间的差值(以秒为单位)是631,065,600。
$date_FIT = new DateTime('1989-12-31 00:00:00', new DateTimeZone('UTC')); $date_UNIX = new DateTime('1970-01-01 00:00:00', new DateTimeZone('UTC')); $diff = $date_FIT->getTimestamp() - $date_UNIX->getTimestamp(); echo 'The difference (in seconds) between FIT and Unix timestamps is '. number_format($diff);
默认情况下,从FIT文件中读取的date_time和local_date_time类型的字段将添加此差值,以便它们可以被视为Unix时间。如果需要FIT时间戳,可以将'garmin_timestamps'选项设置为true。
用开发者数据覆盖
FIT标准允许开发者定义数据的意义,而不需要修改正在使用的FIT配置文件。他们可以定义已纳入标准的数据 - 例如HR、踏频、功率等。默认情况下,如果开发者这样做,数据将覆盖常规$pFFA->data_mesgs['record']
数组中的任何内容。如果您不希望发生这种情况,请将'overwrite_with_dev_data'选项设置为false。数据仍将在$pFFA->data_mesgs['developer_data']
中可用。
分析
以下函数返回可用于创建表格/图表的数据数组
array $pFFA->hrPartionedHRmaximum(int $hr_maximum); array $pFFA->hrPartionedHRreserve(int $hr_resting, int $hr_maximum); array $pFFA->powerPartioned(int $functional_threshold_power); array $pFFA->powerHistogram(int $bucket_width = 25);
要使用户对这些函数有更高级的控制,或与其他传感器数据(例如踏频或速度)一起使用,请使用底层函数
array $pFFA->partitionData(string $record_field='', $thresholds=null, bool $percentages = true, bool $labels_for_keys = true); array $pFFA->histogram(int $bucket_width=25, string $record_field='');
存在一些函数,可以根据用户提供的数据的百分比来确定阈值
array $pFFA->hrZonesMax(int $hr_maximum, array $percentages_array=[0.60, 0.75, 0.85, 0.95]); array $pFFA->hrZonesReserve(int $hr_resting, int $hr_maximum, array $percentages_array=[0.60, 0.65, 0.75, 0.82, 0.89, 0.94 ]) { array $pFFA->powerZones(int $functional_threshold_power, array $percentages_array=[0.55, 0.75, 0.90, 1.05, 1.20, 1.50]);
心率
存在一个分析心率数据的函数
// hr_FT is heart rate at Functional Threshold, or Lactate Threshold Heart Rate array $pFFA->hrMetrics(int $hr_resting, int $hr_maximum, string $hr_FT, $gender); // e.g. $pFFA->hrMetrics(52, 189, 172, 'male');
心率指标
- TRIMP(训练冲击)
- 强度因子
功率
存在三个分析功率数据的函数
array $pFFA->powerMetrics(int $functional_threshold_power); array $pFFA->criticalPower(int or array $time_periods); // e.g. 300 or [600, 900] array $pFFA->quadrantAnalysis(float $crank_length, int $ftp, int $selected_cadence = 90, bool $use_timestamps = false); // Crank length in metres
功率指标
- 平均功率
- 千焦耳
- 标准化功率(估算如果您的功率输出保持恒定的话)
- 变异性指数(标准化功率/平均功率的比率)
- 强度因子(标准化功率/功能阈限功率的比率)
- 训练压力评分(基于相对强度和持续时间的工作量)
临界功率(或最大努力)是在活动期间在指定时间内保持的最高平均功率。您可以为单个时间段(以秒为单位)或时间段数组提供。
象限分析通过比较踏频和功率来查看踏频和力,从而提供对自行车骑行神经肌肉需求的洞察。
请注意,$pFFA->criticalPower
和某些功率指标(标准化功率、变异性指数、强度因子、训练压力评分)如果服务器上已加载PHP Trader扩展,将使用该扩展。如果扩展未加载,则将使用内置的简单移动平均算法,这对于大型文件来说性能要差得多!
功率分析演示可在此处获得。
其他方法
返回以时间戳为键的布尔值数组。true == 计时器暂停(例如自动暂停)
array isPaused()
返回包含请求骑行数据的JSON对象
array getJSON(float $crank_length = null, int $ftp = null, array $data_required = ['all'], int $selected_cadence = 90) /** * $data_required can be ['all'] or a combination of: * ['timestamp', 'paused', 'temperature', 'lap', 'position_lat', 'position_long', 'distance', 'altitude', 'speed', 'heart_rate', 'cadence', 'power', 'quadrant-analysis'] */
返回齿轮更换信息的数组(如果有,例如使用Shimano D-Fly无线Di2发射器)
// By default, time spent in a gear whilst the timer is paused (e.g. autopause) is ignored. Set to false to include. array gearChanges($bIgnoreTimerPaused = true)
认可
此类已使用由ANT(thisisant.com)提供的软件开发工具包(SDK)中可用的信息创建。
最低限度,我建议阅读SDK中包含的三个PDF文件
- FIT文件类型描述
- FIT SDK入门指南
- 灵活且可互操作的数据传输(FIT)协议
接着是'Profile.xls'电子表格和Java/C/C++示例。