From: Dustin Walde Date: Sun, 25 Jun 2023 22:14:48 +0000 (-0700) Subject: Add mtrack to gpx code X-Git-Url: https://git.walde.dev/?a=commitdiff_plain;h=249aa9a38600afcf40dcb9e82e5b6505d8cbcf52;p=mtrack_to_gpx Add mtrack to gpx code - main file mtrack_to_gpx to handle command line args + load file - gpx_builder creates the xml document --- diff --git a/mtrack_to_gpx.py b/mtrack_to_gpx.py new file mode 100644 index 0000000..c32297d --- /dev/null +++ b/mtrack_to_gpx.py @@ -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 index 0000000..da91510 --- /dev/null +++ b/src/gpx_builder.py @@ -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, + ) +