aboutsummaryrefslogtreecommitdiff
path: root/fietsboek/convert.py
blob: bf0664af191fd58d1be1d42c77aaa31f3d9991fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
"""Conversion functions to convert between various recording formats."""
import fitparse
from gpxpy.gpx import GPX, GPXTrack, GPXTrackPoint, GPXTrackSegment

FIT_RECORD_FIELDS = ["position_lat", "position_long", "altitude", "timestamp"]


def semicircles_to_deg(circles: int) -> float:
    """Convert semicircles coordinate to degree coordinate.

    :param circles: The coordinate value in semicircles.
    :return: The coordinate in degrees.
    """
    return circles * (180 / 2**31)


def from_fit(data: bytes) -> GPX:
    """Reads a .fit as GPX data.

    This uses the fitparse_ library under the hood.

    .. _fitparse: https://pypi.org/project/fitparse/

    :param data: The input bytes.
    :return: The converted structure.
    """
    fitfile = fitparse.FitFile(data)
    points = []
    for record in fitfile.get_messages("record"):
        values = record.get_values()
        try:
            if any(values[field] is None for field in FIT_RECORD_FIELDS):
                continue
            point = GPXTrackPoint(
                latitude=semicircles_to_deg(values["position_lat"]),
                longitude=semicircles_to_deg(values["position_long"]),
                elevation=values["altitude"],
                time=values["timestamp"],
            )
        except KeyError:
            pass
        else:
            points.append(point)
    track = GPXTrack()
    track.segments = [GPXTrackSegment(points)]
    gpx = GPX()
    gpx.tracks = [track]
    return gpx


__all__ = ["from_fit"]