Skip to content

Instantly share code, notes, and snippets.

@mrvdb
Last active February 5, 2020 07:38
Show Gist options
  • Select an option

  • Save mrvdb/c517f216b54facfc6ce9685720d331ba to your computer and use it in GitHub Desktop.

Select an option

Save mrvdb/c517f216b54facfc6ce9685720d331ba to your computer and use it in GitHub Desktop.

Revisions

  1. mrvdb revised this gist Oct 15, 2019. 1 changed file with 17 additions and 16 deletions.
    33 changes: 17 additions & 16 deletions suuntoapp2gpx
    Original file line number Diff line number Diff line change
    @@ -61,23 +61,24 @@ def gpx_track(zip):
    suunto_json = json.load(json_data)

    for s in suunto_json["Samples"]:
    sample = s["Attributes"]["suunto/sml"]["Sample"]
    # See if we have enough for a trackpoint
    if all(key in sample for key in TRKPT):
    # Lat and long are radians
    # To decimal degrees = * 180 / PI
    lat = (sample["Latitude"] * 180) / math.pi
    lon = (sample["Longitude"] * 180) / math.pi

    # I'm assuming this is in meters, and we can use it as is
    ele = sample['GPSAltitude'] if 'GPSAltitude' in sample else 0

    time = datetime.datetime.fromisoformat(sample['UTC'])

    # Create the gpx point
    point = gpxpy.gpx.GPXTrackPoint(latitude=lat, longitude=lon,
    if "Sample" in s["Attributes"]["suunto/sml"]:
    sample = s["Attributes"]["suunto/sml"]["Sample"]
    # See if we have enough for a trackpoint
    if all(key in sample for key in TRKPT):
    # Lat and long are radians
    # To decimal degrees = * 180 / PI
    lat = (sample["Latitude"] * 180) / math.pi
    lon = (sample["Longitude"] * 180) / math.pi

    # I'm assuming this is in meters, and we can use it as is
    ele = sample['GPSAltitude'] if 'GPSAltitude' in sample else 0

    time = datetime.datetime.fromisoformat(sample['UTC'])

    # Create the gpx point
    point = gpxpy.gpx.GPXTrackPoint(latitude=lat, longitude=lon,
    time=time, elevation=ele)
    segment.points.append(point)
    segment.points.append(point)

    # Write out the gpx file
    with open(zip.filename.replace(".zip", ".gpx"), "w") as out:
  2. mrvdb revised this gist Apr 21, 2019. 1 changed file with 19 additions and 10 deletions.
    29 changes: 19 additions & 10 deletions suuntoapp2gpx
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,15 @@
    #!/usr/bin/env python
    # -*- mode:python -*-
    # Convert suunto zip files (which contain json files) to a gpx file
    # Until Suunto gets their act together and let me have my own data normally.
    #
    # Converts suunto zip files (which contain json files) to a gpx file
    # until Suunto gets their act together and let me have my own data in
    # a normal way.
    # Needs: python 3.7
    #
    # These zip files are producted by the Suunto app and typically on
    # android are located at:
    # <Internal Storage>/Android/data/com.stt.suunto/files/smlzip/
    #

    import sys
    import gpxpy
    @@ -12,21 +19,21 @@ import datetime
    import zipfile
    import math

    # The relevant json snippets which are on a json array 'Samples'
    # The relevant json snippet which is in a json array 'Samples'
    # looks like this:

    # {
    # "Attributes": {
    # "suunto/sml": {
    # "Sample": {
    # "GPSAltitude": 94, <-- assuming meters
    # "Latitude": 0.88924328690504395, <-- this value is weird
    # "Longitude": 0.10261437316962527, <-- this value is weird
    # "Latitude": 0.88924328690504395, <-- in radians
    # "Longitude": 0.10261437316962527, <-- in radians
    # "UTC": "2019-04-18T07:25:29.000+00:00" <-- assumed what gps thinks of time?
    # }
    # }
    # },
    # "Source": "suunto-123456789", <-- id of watch
    # "Source": "suunto-123456789", <-- number is the id of the device
    # "TimeISO8601": "2019-04-18T09:25:29.000+02:00" <-- assumed what watch thinks of time?
    # },

    @@ -41,7 +48,7 @@ def gpx_track(zip):
    # Create the main gpx object
    gpx = gpxpy.gpx.GPX()

    # We are getting one track presumably, from the points we recorded
    # We are getting one track presumably from the points we recorded
    track = gpxpy.gpx.GPXTrack()
    gpx.tracks.append(track)

    @@ -57,10 +64,10 @@ def gpx_track(zip):
    sample = s["Attributes"]["suunto/sml"]["Sample"]
    # See if we have enough for a trackpoint
    if all(key in sample for key in TRKPT):
    # Lat and long are floats between 0 and 1
    # Lat and long are radians
    # To decimal degrees = * 180 / PI
    lat = (sample["Latitude"] * 180) / math.pi # Used to be * 57.2958320392
    lon = (sample["Longitude"] * 180) / math.pi # Used to be * 57.2952851192
    lat = (sample["Latitude"] * 180) / math.pi
    lon = (sample["Longitude"] * 180) / math.pi

    # I'm assuming this is in meters, and we can use it as is
    ele = sample['GPSAltitude'] if 'GPSAltitude' in sample else 0
    @@ -83,3 +90,5 @@ if __name__ == "__main__":
    # There should be a samples.json in the zip file
    if SUUNTO_SAMPLES in zip.namelist():
    gpx_track(zip)
    else:
    print("No track samples found in zip file!")
  3. mrvdb revised this gist Apr 21, 2019. 1 changed file with 0 additions and 88 deletions.
    88 changes: 0 additions & 88 deletions suuntoapp2gpx.py
    Original file line number Diff line number Diff line change
    @@ -1,88 +0,0 @@
    #!/usr/bin/env python
    # -*- mode:python -*-
    # Convert suunto zip files (which contain json files) to a gpx file
    # Until Suunto gets their act together and let me have my own data normally.
    # Needs: python 3.7

    import sys
    import gpxpy
    import gpxpy.gpx
    import json
    import datetime
    import zipfile

    # The relevant json snippets which are on a json array 'Samples'
    # looks like this:

    # {
    # "Attributes": {
    # "suunto/sml": {
    # "Sample": {
    # "GPSAltitude": 94, <-- assuming meters
    # "Latitude": 0.88924328690504395, <-- this value is weird
    # "Longitude": 0.10261437316962527, <-- this value is weird
    # "UTC": "2019-04-18T07:25:29.000+00:00" <-- assumed what gps thinks of time?
    # }
    # }
    # },
    # "Source": "suunto-123456789", <-- id of watch
    # "TimeISO8601": "2019-04-18T09:25:29.000+02:00" <-- assumed what watch thinks of time?
    # },

    # Suunto specific stuff
    SUUNTO_SAMPLES = 'samples.json'


    def gpx_track(zip):
    # Three keys make a trackpoint
    TRKPT = ('Latitude', 'Longitude', 'UTC')

    # Create the main gpx object
    gpx = gpxpy.gpx.GPX()

    # We are getting one track presumably, from the points we recorded
    track = gpxpy.gpx.GPXTrack()
    gpx.tracks.append(track)

    # Points are added to segments (take breaks into account later?)
    segment = gpxpy.gpx.GPXTrackSegment()
    track.segments.append(segment)

    # Read in the json file
    with zip.open(SUUNTO_SAMPLES, 'r') as json_data:
    suunto_json = json.load(json_data)

    for s in suunto_json["Samples"]:
    sample = s["Attributes"]["suunto/sml"]["Sample"]
    # See if we have enough for a trackpoint
    if all(key in sample for key in TRKPT):
    # Not sure yet what units these are
    # - they seem to be between 0 and 1
    # - it looks like a linear transformation
    # (the shape of the route is maintained)
    # The numbers I determined from basically
    # one point, wtf are they?
    lat = 57.2958320392 * sample["Latitude"]
    lon = 57.2952851192 * sample["Longitude"]

    # I'm assuming this is in meters, and we can use it as is
    ele = sample['GPSAltitude'] if 'GPSAltitude' in sample else 0

    time = datetime.datetime.fromisoformat(sample['UTC'])

    # Create the gpx point
    point = gpxpy.gpx.GPXTrackPoint(latitude=lat, longitude=lon,
    time=time, elevation=ele)
    segment.points.append(point)

    # Write out the gpx file
    with open(zip.filename.replace(".zip", ".gpx"), "w") as out:
    out.write(gpx.to_xml())


    if __name__ == "__main__":
    # Argument is expected to be a zip file
    with zipfile.ZipFile(sys.argv[1]) as zip:
    # There should be a samples.json in the zip file
    if SUUNTO_SAMPLES in zip.namelist():
    gpx_track(zip)
  4. mrvdb revised this gist Apr 21, 2019. 1 changed file with 88 additions and 0 deletions.
    88 changes: 88 additions & 0 deletions suuntoapp2gpx.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,88 @@
    #!/usr/bin/env python
    # -*- mode:python -*-
    # Convert suunto zip files (which contain json files) to a gpx file
    # Until Suunto gets their act together and let me have my own data normally.
    # Needs: python 3.7

    import sys
    import gpxpy
    import gpxpy.gpx
    import json
    import datetime
    import zipfile

    # The relevant json snippets which are on a json array 'Samples'
    # looks like this:

    # {
    # "Attributes": {
    # "suunto/sml": {
    # "Sample": {
    # "GPSAltitude": 94, <-- assuming meters
    # "Latitude": 0.88924328690504395, <-- this value is weird
    # "Longitude": 0.10261437316962527, <-- this value is weird
    # "UTC": "2019-04-18T07:25:29.000+00:00" <-- assumed what gps thinks of time?
    # }
    # }
    # },
    # "Source": "suunto-123456789", <-- id of watch
    # "TimeISO8601": "2019-04-18T09:25:29.000+02:00" <-- assumed what watch thinks of time?
    # },

    # Suunto specific stuff
    SUUNTO_SAMPLES = 'samples.json'


    def gpx_track(zip):
    # Three keys make a trackpoint
    TRKPT = ('Latitude', 'Longitude', 'UTC')

    # Create the main gpx object
    gpx = gpxpy.gpx.GPX()

    # We are getting one track presumably, from the points we recorded
    track = gpxpy.gpx.GPXTrack()
    gpx.tracks.append(track)

    # Points are added to segments (take breaks into account later?)
    segment = gpxpy.gpx.GPXTrackSegment()
    track.segments.append(segment)

    # Read in the json file
    with zip.open(SUUNTO_SAMPLES, 'r') as json_data:
    suunto_json = json.load(json_data)

    for s in suunto_json["Samples"]:
    sample = s["Attributes"]["suunto/sml"]["Sample"]
    # See if we have enough for a trackpoint
    if all(key in sample for key in TRKPT):
    # Not sure yet what units these are
    # - they seem to be between 0 and 1
    # - it looks like a linear transformation
    # (the shape of the route is maintained)
    # The numbers I determined from basically
    # one point, wtf are they?
    lat = 57.2958320392 * sample["Latitude"]
    lon = 57.2952851192 * sample["Longitude"]

    # I'm assuming this is in meters, and we can use it as is
    ele = sample['GPSAltitude'] if 'GPSAltitude' in sample else 0

    time = datetime.datetime.fromisoformat(sample['UTC'])

    # Create the gpx point
    point = gpxpy.gpx.GPXTrackPoint(latitude=lat, longitude=lon,
    time=time, elevation=ele)
    segment.points.append(point)

    # Write out the gpx file
    with open(zip.filename.replace(".zip", ".gpx"), "w") as out:
    out.write(gpx.to_xml())


    if __name__ == "__main__":
    # Argument is expected to be a zip file
    with zipfile.ZipFile(sys.argv[1]) as zip:
    # There should be a samples.json in the zip file
    if SUUNTO_SAMPLES in zip.namelist():
    gpx_track(zip)
  5. mrvdb renamed this gist Apr 21, 2019. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  6. mrvdb created this gist Apr 21, 2019.
    85 changes: 85 additions & 0 deletions suuntoapp2gpx.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,85 @@
    #!/usr/bin/env python
    # -*- mode:python -*-
    # Convert suunto zip files (which contain json files) to a gpx file
    # Until Suunto gets their act together and let me have my own data normally.
    # Needs: python 3.7

    import sys
    import gpxpy
    import gpxpy.gpx
    import json
    import datetime
    import zipfile
    import math

    # The relevant json snippets which are on a json array 'Samples'
    # looks like this:

    # {
    # "Attributes": {
    # "suunto/sml": {
    # "Sample": {
    # "GPSAltitude": 94, <-- assuming meters
    # "Latitude": 0.88924328690504395, <-- this value is weird
    # "Longitude": 0.10261437316962527, <-- this value is weird
    # "UTC": "2019-04-18T07:25:29.000+00:00" <-- assumed what gps thinks of time?
    # }
    # }
    # },
    # "Source": "suunto-123456789", <-- id of watch
    # "TimeISO8601": "2019-04-18T09:25:29.000+02:00" <-- assumed what watch thinks of time?
    # },

    # Suunto specific stuff
    SUUNTO_SAMPLES = 'samples.json'


    def gpx_track(zip):
    # Three keys make a trackpoint
    TRKPT = ('Latitude', 'Longitude', 'UTC')

    # Create the main gpx object
    gpx = gpxpy.gpx.GPX()

    # We are getting one track presumably, from the points we recorded
    track = gpxpy.gpx.GPXTrack()
    gpx.tracks.append(track)

    # Points are added to segments (take breaks into account later?)
    segment = gpxpy.gpx.GPXTrackSegment()
    track.segments.append(segment)

    # Read in the json file
    with zip.open(SUUNTO_SAMPLES, 'r') as json_data:
    suunto_json = json.load(json_data)

    for s in suunto_json["Samples"]:
    sample = s["Attributes"]["suunto/sml"]["Sample"]
    # See if we have enough for a trackpoint
    if all(key in sample for key in TRKPT):
    # Lat and long are floats between 0 and 1
    # To decimal degrees = * 180 / PI
    lat = (sample["Latitude"] * 180) / math.pi # Used to be * 57.2958320392
    lon = (sample["Longitude"] * 180) / math.pi # Used to be * 57.2952851192

    # I'm assuming this is in meters, and we can use it as is
    ele = sample['GPSAltitude'] if 'GPSAltitude' in sample else 0

    time = datetime.datetime.fromisoformat(sample['UTC'])

    # Create the gpx point
    point = gpxpy.gpx.GPXTrackPoint(latitude=lat, longitude=lon,
    time=time, elevation=ele)
    segment.points.append(point)

    # Write out the gpx file
    with open(zip.filename.replace(".zip", ".gpx"), "w") as out:
    out.write(gpx.to_xml())


    if __name__ == "__main__":
    # Argument is expected to be a zip file
    with zipfile.ZipFile(sys.argv[1]) as zip:
    # There should be a samples.json in the zip file
    if SUUNTO_SAMPLES in zip.namelist():
    gpx_track(zip)
  7. mrvdb created this gist Apr 20, 2019.
    88 changes: 88 additions & 0 deletions suuntoapp2gpx.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,88 @@
    #!/usr/bin/env python
    # -*- mode:python -*-
    # Convert suunto zip files (which contain json files) to a gpx file
    # Until Suunto gets their act together and let me have my own data normally.
    # Needs: python 3.7

    import sys
    import gpxpy
    import gpxpy.gpx
    import json
    import datetime
    import zipfile

    # The relevant json snippets which are on a json array 'Samples'
    # looks like this:

    # {
    # "Attributes": {
    # "suunto/sml": {
    # "Sample": {
    # "GPSAltitude": 94, <-- assuming meters
    # "Latitude": 0.88924328690504395, <-- this value is weird
    # "Longitude": 0.10261437316962527, <-- this value is weird
    # "UTC": "2019-04-18T07:25:29.000+00:00" <-- assumed what gps thinks of time?
    # }
    # }
    # },
    # "Source": "suunto-123456789", <-- id of watch
    # "TimeISO8601": "2019-04-18T09:25:29.000+02:00" <-- assumed what watch thinks of time?
    # },

    # Suunto specific stuff
    SUUNTO_SAMPLES = 'samples.json'


    def gpx_track(zip):
    # Three keys make a trackpoint
    TRKPT = ('Latitude', 'Longitude', 'UTC')

    # Create the main gpx object
    gpx = gpxpy.gpx.GPX()

    # We are getting one track presumably, from the points we recorded
    track = gpxpy.gpx.GPXTrack()
    gpx.tracks.append(track)

    # Points are added to segments (take breaks into account later?)
    segment = gpxpy.gpx.GPXTrackSegment()
    track.segments.append(segment)

    # Read in the json file
    with zip.open(SUUNTO_SAMPLES, 'r') as json_data:
    suunto_json = json.load(json_data)

    for s in suunto_json["Samples"]:
    sample = s["Attributes"]["suunto/sml"]["Sample"]
    # See if we have enough for a trackpoint
    if all(key in sample for key in TRKPT):
    # Not sure yet what units these are
    # - they seem to be between 0 and 1
    # - it looks like a linear transformation
    # (the shape of the route is maintained)
    # The numbers I determined from basically
    # one point, wtf are they?
    lat = 57.2958320392 * sample["Latitude"]
    lon = 57.2952851192 * sample["Longitude"]

    # I'm assuming this is in meters, and we can use it as is
    ele = sample['GPSAltitude'] if 'GPSAltitude' in sample else 0

    time = datetime.datetime.fromisoformat(sample['UTC'])

    # Create the gpx point
    point = gpxpy.gpx.GPXTrackPoint(latitude=lat, longitude=lon,
    time=time, elevation=ele)
    segment.points.append(point)

    # Write out the gpx file
    with open(zip.filename.replace(".zip", ".gpx"), "w") as out:
    out.write(gpx.to_xml())


    if __name__ == "__main__":
    # Argument is expected to be a zip file
    with zipfile.ZipFile(sys.argv[1]) as zip:
    # There should be a samples.json in the zip file
    if SUUNTO_SAMPLES in zip.namelist():
    gpx_track(zip)