-
-
Save andrewyatz/165c7bab69b30ed1b359fa131416c9c3 to your computer and use it in GitHub Desktop.
Rungap for iOS exports GPS data as JSON file in the free version. This script converts it to GPX. Tested with python3.6. Might need to install required modules. Simply place either the metadata and data json files, or the complete zip file in the same directoryas the script and run it. Warning: Does barely any error checking
This file contains 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
import xml.etree.cElementTree as ElementTree | |
import json, pytz, zipfile, unicodedata, re | |
from datetime import datetime | |
from os import listdir | |
from os.path import isfile, join | |
import glob | |
def slugify(value): | |
""" | |
Normalizes string, converts to lowercase, removes non-alpha characters. | |
Slightly modified from https://github.com/django/django/blob/master/django/utils/text.py | |
""" | |
value = str(value) | |
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii') | |
value = re.sub(r'[^\w\s-]', '', value).strip().lower() | |
return re.sub(r'[-\s]+', '-', value) | |
creator = "GapX" | |
version = "1.1" | |
zip_files = glob.glob("*.zip") | |
for zip_file in zip_files: | |
print("Unzipping " + zip_file) | |
zip_ref = zipfile.ZipFile(zip_file, 'r') | |
for info in zip_ref.infolist(): | |
print(info.filename) | |
if info.filename.endswith("metadata.json") or info.filename.endswith("rungap.json"): | |
zip_ref.extract(info) | |
zip_ref.close() | |
metadata_files = glob.glob("*metadata.json") | |
data_files = glob.glob("*rungap.json") | |
print("Found metadata files") | |
print(metadata_files) | |
print("Found data files") | |
print(data_files) | |
if len(metadata_files) != len(data_files): | |
print("Error, number of metadata files does not match number of datafiles!") | |
exit(1) | |
for idx, metadata_file in enumerate(metadata_files): | |
print("=========") | |
print("Parsing " + metadata_file + " and " + data_files[idx]) | |
metadata_data = json.load(open(metadata_file)) | |
data = json.load(open(data_files[idx])) | |
root = ElementTree.Element("gpx") | |
root.set("xmlns","http://www.topografix.com/GPX/1/1") | |
root.set("creator", creator) | |
root.set("version", version) | |
metadata = ElementTree.SubElement(root, "metadata") | |
name = metadata_data["title"] | |
desc = metadata_data["description"] | |
print("Route name: " + name) | |
print("Route description: " + desc) | |
ElementTree.SubElement(metadata, "name").text = name | |
ElementTree.SubElement(metadata, "desc").text = desc | |
ElementTree.SubElement(metadata, "time").text = metadata_data["startTime"]["time"] | |
timezone = pytz.timezone(metadata_data["startTime"]["timeZone"]) | |
source = metadata_data["source"] + " exported by Rungap for iOS, version " + metadata_data["appversion"] | |
track = ElementTree.SubElement(root, "trk") | |
ElementTree.SubElement(track, "name").text = name | |
ElementTree.SubElement(track, "desc").text = desc | |
ElementTree.SubElement(track, "src").text = source | |
segment = ElementTree.SubElement(track, "trkseg") | |
print("Found " + str(len(data["laps"][0]["points"])) + " track points") | |
for point in data["laps"][0]["points"]: | |
if ("lat" in point and "lon" in point and "ele" in point and "time" in point): | |
trkpt = ElementTree.SubElement(segment, "trkpt", lat=str(point["lat"]), lon=str(point["lon"])) | |
ElementTree.SubElement(trkpt, "ele").text = str(point["ele"]) | |
ElementTree.SubElement(trkpt, "time").text = datetime.fromtimestamp(point["time"], timezone).isoformat() | |
gpx_filename = slugify(name + " - " + datetime.now().isoformat()) + ".gpx" | |
print("Writing " + gpx_filename) | |
tree = ElementTree.ElementTree(root) | |
tree.write(gpx_filename, "UTF-8", True) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment