Created
July 16, 2012 08:35
-
-
Save k9ordon/3121560 to your computer and use it in GitHub Desktop.
exports nike+ runs to gpx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<pre> | |
strt importing gpx files ... | |
<?php | |
require_once 'lib/init.php'; // init $n stuff (login) | |
$dir = "import"; | |
$runs = $n->activities(); | |
foreach($runs->activities as $a) { | |
$runId = $a->activityId; | |
$fileName = sprintf('%s/%s.gpx', $dir, $runId); | |
if(!file_exists($fileName)) { | |
echo "importing run " . $fileName . "\n"; | |
$run = $n->run($runId); | |
if($run === NULL) { | |
echo "cannot import " . $runId . "\n"; | |
continue; | |
} | |
file_put_contents($fileName, $n->toGpx($run)); | |
} | |
} | |
?> | |
eof |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<? | |
class NikePlusPHPGpxExport extends NikePlusPHP { | |
/** | |
* toGpx() | |
* outputs a run object to a runtastic importable gpx document | |
* | |
* @param object $run output from run() | |
* | |
* @return string gpx string | |
*/ | |
public function toGpx($run) { | |
$activity = $run->activity; | |
$waypoints = $run->activity->geo->waypoints; | |
$startTime = strtotime($run->activity->startTimeUtc); | |
$name = 'Nike+ ' . $run->activity->name; | |
$description = $run->activity->tags->note; | |
$heartRate = null; | |
$distance = null; | |
foreach($run->activity->history as $hi) { | |
if($hi->type == 'HEARTRATE') $heartRate = $hi; | |
if($hi->type == 'DISTANCE') $distance = $hi; | |
} | |
$b = new XMLWriter(); | |
$b->openMemory(); | |
$b->setIndent(true); | |
$b->setIndentString(" "); | |
$b->startDocument("1.0", "UTF-8"); | |
$b->startElement('gpx'); | |
$b->writeAttribute('version', '0.1'); | |
$b->writeAttribute('creator', 'nikeplusphp'); | |
$b->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); | |
$b->writeAttribute('xmlns', 'http://www.topografix.com/GPX/1/1'); | |
$b->writeAttribute('xsi:schemaLocation', 'http://www.topografix.com/GPX/1/1 http://www.topografix.com/gpx/1/1/gpx.xsd'); | |
$b->writeAttribute('xmlns:gpxtpx', 'http://www.garmin.com/xmlschemas/TrackPointExtension/v1'); | |
$b->writeAttribute('xmlns:gpxx', 'http://www.garmin.com/xmlschemas/GpxExtensions/v3'); | |
// metadata | |
$b->startElement('metadata'); | |
$b->writeElement('name', $name); | |
$b->writeElement('desc', $description); | |
// get min/max lat/lng | |
$minLon = 10000; | |
$maxLon = -10000; | |
$minLat = 10000; | |
$maxLat = -10000; | |
foreach($waypoints as $wp) { | |
if($wp->lon > $maxLon) $maxLon = $wp->lon; | |
if($wp->lon < $minLon) $minLon = $wp->lon; | |
if($wp->lat > $maxLat) $maxLat = $wp->lat; | |
if($wp->lat < $minLat) $minLat = $wp->lat; | |
} | |
$b->startElement('bounds'); | |
$b->writeAttribute('maxlon', $maxLon); | |
$b->writeAttribute('minlon', $minLon); | |
$b->writeAttribute('maxlat', $maxLat); | |
$b->writeAttribute('minlat', $minLat); | |
$b->endElement(); // EO bounds | |
$b->endElement(); // EO metadata | |
// track | |
$b->startElement('trk'); | |
$b->writeElement('name', 'trkName ' . time()); | |
$b->writeElement('type', 'Run'); | |
$b->startElement('trkseg'); | |
foreach($waypoints as $index => $wp) { | |
$b->startElement('trkpt'); | |
$b->writeAttribute('lat', $wp->lat); | |
$b->writeAttribute('lon', $wp->lon); | |
$b->writeElement('ele', $wp->ele); | |
$b->writeElement('time', date('Y-m-d\TH:i:s', $startTime+$index)); | |
$b->startElement('extensions'); | |
$b->startElement('gpxtpx:TrackPointExtension'); | |
if($heartRate !== null) { | |
$hrKey = (int) floor($index/$heartRate->intervalMetric); | |
if(array_key_exists($hrKey, $heartRate->values)) { | |
$b->writeElement('gpxtpx:hr', $heartRate->values[$hrKey]); | |
} | |
} | |
$b->endElement(); // EO gpxtpx:TrackPointExtension | |
$b->endElement(); // EO extensions | |
$b->endElement(); // EO trkpt | |
} | |
$b->endElement(); // EO trkseg | |
$b->endElement(); // EO trk | |
$b->endElement(); // EO gpx | |
$b->endDocument(); | |
return $b->outputMemory(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I only found this issue after I imported a GPX file into another running app and was told I'd managed to run at over 17 miles per hour. I don't know if this is the result of a change by Nike or if it's always been an issue. $index taken from the way points array is not a duration reference, so the times being set for each way point in the GPX are wrong. For whatever reason the Nike output does not include a time or duration value with their way point data. They do have separate KM and Mile split arrays which include a duration for each point, but then you lose a load of way points and I imagine the map would be messed up. The only solution I could come up with was to create an even increment based on the duration and number of way points.
$incr = ($duration/1000)/count($waypoints);
foreach($waypoints as $index => $wp) {
...
if ($index == 0) {
$b->writeElement('time', date('Y-m-d\TH:i:s', $startTime));
} else if ($index == (count($waypoints) - 1)) {
$b->writeElement('time', date('Y-m-d\TH:i:s', $startTime+($duration/1000)));
} else {
$b->writeElement('time', date('Y-m-d\TH:i:s', $startTime+($incr*$index)));
}
...
}