]> git.walde.dev - mtrack_to_gpx/commitdiff
Add mtrack to gpx code
authorDustin Walde <redacted>
Sun, 25 Jun 2023 22:14:48 +0000 (15:14 -0700)
committerDustin Walde <redacted>
Sun, 25 Jun 2023 22:14:48 +0000 (15:14 -0700)
- main file mtrack_to_gpx to handle command line args + load file
- gpx_builder creates the xml document

mtrack_to_gpx.py [new file with mode: 0644]
src/gpx_builder.py [new file with mode: 0644]

diff --git a/mtrack_to_gpx.py b/mtrack_to_gpx.py
new file mode 100644 (file)
index 0000000..c32297d
--- /dev/null
@@ -0,0 +1,51 @@
+from os import listdir, path
+from sys import argv
+
+import src.Track_pb2 as track_pb
+from src.gpx_builder import write_gpx_from_mtrack_data
+
+from typing import List, Optional
+
+
+MT_EXT = ".mtrack"
+OPTIONS = {
+    "-t": "tag",
+    "--tag": "tag",
+}
+
+
+def convert_file(path_in: str, keywords: List[str]):
+    track = track_pb.Track()
+    path_out = path.splitext(path_in)[0] + ".gpx"
+    with open(path_in, "rb") as file:
+        track.ParseFromString(file.read())
+        write_gpx_from_mtrack_data(track, path_out, *keywords)
+
+
+def main(args: List[str]):
+    option: Optional[str] = None
+    labels = []
+    path_in = None
+    for arg in args:
+        if option == "tag":
+            labels.append(arg)
+        else:
+            path_in = arg
+
+        option = OPTIONS.get(arg)
+
+    if path_in is None:
+        exit(1)
+
+    if path.isdir(path_in):
+        for file in listdir(path_in):
+            if file.endswith(MT_EXT):
+                file_path = path.join(path_in, file)
+                convert_file(file_path, labels)
+    elif path.isfile(path_in) and path_in.endswith(MT_EXT):
+        convert_file(path_in, labels)
+    
+
+if __name__ == "__main__":
+    main(argv[1:])
+
diff --git a/src/gpx_builder.py b/src/gpx_builder.py
new file mode 100644 (file)
index 0000000..da91510
--- /dev/null
@@ -0,0 +1,66 @@
+from datetime import datetime
+import xml.etree.ElementTree as ET
+
+from .Track_pb2 import Track
+
+
+KEYWORD_DELIMITER = ','
+NS = {
+    "gpx": "http://www.topografix.com/GPX/1/1"
+}
+
+
+def write_gpx_from_mtrack_data(track: Track, path: str, *keywords: str):
+    root = ET.Element('gpx')
+    tree = ET.ElementTree(root)
+
+    root.attrib['creator'] = "mtrack_to_gpx;see also: Trekarta https://trekarta.info"
+    root.attrib['xmlns'] = NS['gpx']
+
+    md = ET.SubElement(root, 'metadata')
+    md_name = ET.SubElement(md, 'name')
+    md_name.text = track.name
+
+    if len(keywords) > 0:
+        kw_el = ET.SubElement(md, 'keywords')
+        kw_el.text = KEYWORD_DELIMITER.join(keywords)
+
+    trk = ET.SubElement(root, 'trk')
+    trk_name = ET.SubElement(trk, 'name')
+    trk_name.text = track.name
+
+    seg = ET.SubElement(trk, 'trkseg')
+    first_time = None
+    for point in track.points:
+        if not point.continuous:
+            seg = ET.SubElement(trk, 'trkseg')
+        pt = ET.SubElement(seg, 'trkpt')
+        pt.attrib['lat'] = f'{point.latitude_e6/1e6:0.6f}'
+        pt.attrib['lon'] = f'{point.longitude_e6/1e6:0.6f}'
+
+        alt = ET.SubElement(pt, 'ele')
+        alt.text = f'{point.altitude:0.3f}'
+
+        hdop = ET.SubElement(pt, 'hdop')
+        hdop.text = f'{point.accuracy/5:0.6f}'
+
+        bearing = ET.SubElement(pt, 'magvar')
+        bearing.text = f'{point.bearing:0.1f}'
+
+        ts = ET.SubElement(pt, 'time')
+        time = datetime.fromtimestamp(point.timestamp/1000)
+        ts.text = time.isoformat()
+
+        if first_time is None:
+            first_time = time
+
+    if first_time is not None:
+        md_time = ET.SubElement(md, 'time')
+        md_time.text = first_time.isoformat()
+
+    tree.write(
+        path,
+        encoding='UTF-8',
+        xml_declaration=True,
+        )
+