Last active
January 9, 2021 15:45
-
-
Save mfn/c94447215dd28c2956e7174402d71808 to your computer and use it in GitHub Desktop.
Convert endomondo json tracking data 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
<?php declare(strict_types=1); | |
/* | |
Usage: php endomondo_json2gpx.php <path_to_file.json> […<path_to_other_file.json>] | |
The endomondo json format parsed here; only the fields actually used by this converted: | |
[ | |
{"sport": "…"}, | |
{"points": [ | |
[ | |
{"location": [[ | |
{"latitude": …}, | |
{"longitude": …} | |
]]}, | |
{"altitude": …}, | |
{"timestamp": "…"} | |
], | |
which will be converted to | |
<?xml version="1.0" encoding="UTF-8"?> | |
<gpx creator="endomondo_json2gpx.php"> | |
<trk> | |
<type>…</type> | |
<trkseg> | |
<trkpt lat="…" lon="…"> | |
<time>…</time> | |
<ele>…</ele> | |
</trkpt> | |
*/ | |
$script = array_shift($argv); | |
$jsonFiles = $argv; | |
if (!$jsonFiles) { | |
echo "ERROR: No *.json files given\n\n"; | |
echo "Usage: $script <1.json> ... <n.json>\n"; | |
exit(1); | |
} | |
foreach ($jsonFiles as $jsonFile) { | |
echo "Loading $jsonFile ...\n"; | |
$data = json_decode(file_get_contents($jsonFile), true); | |
$json = transformJson($data); | |
$xml = convertJsonToGpx($json); | |
if (!$xml) { | |
echo "WARNING: no usable points found, skipping file\n"; | |
continue; | |
} | |
$gpxFile = str_replace('.json', '.gpx', $jsonFile); | |
echo "Writing $gpxFile ...\n"; | |
$xml->save($gpxFile); | |
} | |
function convertJsonToGpx(array $json): ?DOMDocument | |
{ | |
$xml = new DOMDocument(); | |
$xml->encoding = 'UTF-8'; | |
$xml->formatOutput = true; | |
$gpx = $xml->createElement('gpx'); | |
$xml->appendChild($gpx); | |
$gpx->setAttribute('creator', 'endomondo_json2gpx.php'); | |
$trk = $xml->createElement('trk'); | |
$gpx->appendChild($trk); | |
$type = $xml->createElement('type', strtolower($json['sport'])); | |
$trk->appendChild($type); | |
$trkseg = $xml->createElement('trkseg'); | |
$trk->appendChild($trkseg); | |
$pointsAdded = 0; | |
foreach ($json['points'] as $point) { | |
$point = transformJson($point); | |
if (!isset($point['location'])) { | |
continue; | |
} | |
$pointsAdded++; | |
$location = transformJson($point['location'][0]); | |
$altitude = $point['altitude'] ?? null; | |
$timestamp = new DateTimeImmutable($point['timestamp']); | |
$trkpt = $xml->createElement('trkpt'); | |
$trkseg->appendChild($trkpt); | |
$trkpt->setAttribute('lat', (string) $location['latitude']); | |
$trkpt->setAttribute('lon', (string) $location['longitude']); | |
$time = $xml->createElement('time', $timestamp->format(DateTimeInterface::ATOM)); | |
$trkpt->appendChild($time); | |
if ($altitude) { | |
$ele = $xml->createElement('ele', (string) $altitude); | |
$trkpt->appendChild($ele); | |
} | |
} | |
if (!$pointsAdded) { | |
return null; | |
} | |
return $xml; | |
} | |
function transformJson(array $data): array | |
{ | |
$json = []; | |
foreach ($data as $datum) { | |
$key = array_key_first($datum); | |
$json[$key] = $datum[$key]; | |
} | |
return $json; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment