Skip to content

Commit 2da48b1

Browse files
committed
Add openambit to TCX conversion scripts and icon
1 parent b38410d commit 2da48b1

4 files changed

Lines changed: 430 additions & 0 deletions

File tree

icon.png

316 KB
Loading

tools/openambit2gpx.py

100644100755
File mode changed.

tools/openambit2tcx-lap.py

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
#!/usr/bin/env python2
2+
3+
""" converts the *.log files produced by openambit in ~/.openambit/ to standard TCX format.
4+
usage: ./openambit2tcx.py inputfile outputFile
5+
required dependecies: python{2,3}-dateutil ; python{2,3}-lxml
6+
"""
7+
8+
#from lxml import etree # does not allow namespace prefixes which are required for gpx extensions; everything else in this script would work otherwise with lxml
9+
#import xml.etree.ElementTree as etree
10+
from lxml import etree
11+
#import math
12+
import sys
13+
import datetime
14+
from dateutil.parser import parse
15+
import StringIO
16+
17+
##############################
18+
## getting input parameters ##
19+
##############################
20+
21+
if len(sys.argv) == 3:
22+
fileIn=sys.argv[1]
23+
fileOut=sys.argv[2]
24+
else:
25+
sys.stderr.write("""\
26+
Convert Openambit *.log files to standard TCX format
27+
usage: {} inputfile outputfile
28+
29+
Openambit *.log files can normally be found in ~/.openambit/
30+
""".format(sys.argv[0]))
31+
sys.exit(1)
32+
33+
###########################################
34+
## setting variables up, starting output ##
35+
###########################################
36+
37+
fOut = open(fileOut, 'w')
38+
39+
out ='<?xml version="1.0"?>\n'
40+
out += '<TrainingCenterDatabase xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2">\n'
41+
out +=' <Activities>\n'
42+
out += ' <Activity Sport="Other">\n'
43+
rootIn = etree.parse(fileIn)
44+
t_time = rootIn.find("Time")
45+
out += ' <Id>' + t_time.text + 'Z</Id>\n'
46+
out += ' <Lap StartTime="' + t_time.text + 'Z">\n'
47+
header = rootIn.find("Log/Header")
48+
duration = header.findtext("Duration")
49+
out += ' <TotalTimeSeconds>' + str(float(duration) / 1000) + '</TotalTimeSeconds>\n'
50+
distance = header.findtext("Distance")
51+
out += ' <DistanceMeters>' + distance + '</DistanceMeters>\n'
52+
header = rootIn.find("Log/Header/Speed")
53+
speedMax = header.findtext("Max")
54+
out += ' <MaximumSpeed>' + str(float(speedMax) / 3600) + '</MaximumSpeed>\n'
55+
# ?Calories is missing from openambit dump files?
56+
out += ' <Track>\n'
57+
58+
59+
latLast=None
60+
lonLast=None
61+
timeLast=None
62+
altitudeLast=None
63+
hrLast=None
64+
cadenceLast=None
65+
powerLast=None
66+
speedLast=None
67+
tempLast=None
68+
airpressureLast=None
69+
latLatest=None
70+
lonLatest=None
71+
timeGPSLatest=None
72+
73+
'''lapCount=0
74+
lapArray=[0]
75+
maxLap=0'''
76+
77+
year = parse(t_time.text, fuzzy=True).year
78+
month = parse(t_time.text, fuzzy=True).month
79+
day = parse(t_time.text, fuzzy=True).day
80+
hour = parse(t_time.text, fuzzy=True).hour
81+
minute = parse(t_time.text, fuzzy=True).minute
82+
second = parse(t_time.text, fuzzy=True).second
83+
startTime = datetime.datetime(year, month, day, hour, minute, second)
84+
85+
###########################
86+
## getting laps data ##
87+
###########################
88+
89+
intervals = []
90+
91+
for element in rootIn.iterfind("Log/Samples/Sample/Lap"):
92+
type_id = element.find('Type').attrib
93+
if type_id['id'] == '1':
94+
datetime_l = element.find('DateTime').text
95+
duration_l = element.find('Duration').text
96+
distance_l = element.find('Distance').text
97+
98+
intervals.append(element)
99+
100+
###########################
101+
## getting activity data ##
102+
###########################
103+
104+
t_activities = etree.Element('Activities')
105+
t_activity = etree.SubElement(t_activities, 'Activity')
106+
t_activity.set('Sport', 'Other')
107+
t_id = etree.SubElement(t_activity, "Id")
108+
t_id.text = t_time.text + 'Z'
109+
110+
timeslot_finish = 0
111+
timeslot_start = 0
112+
113+
for lap in intervals:
114+
type_id = lap.find('Type').attrib
115+
datetime_l = lap.find('DateTime').text
116+
duration_l = int(lap.find('Duration').text)
117+
distance_l = lap.find('Distance').text
118+
timeslot_start = timeslot_finish + 1
119+
timeslot_finish += duration_l
120+
121+
out += ' <Lap StartTime="' + datetime_l + 'Z">\n'
122+
out += ' <TotalTimeSeconds>' + str(float(duration_l) / 1000) + '</TotalTimeSeconds>\n'
123+
out += ' <DistanceMeters>' + distance_l + '</DistanceMeters>\n'
124+
#out += ' <MaximumSpeed>' + "" + '</MaximumSpeed>\n' # not needed in
125+
# ?Calories is missing from openambit dump files?
126+
out += ' <Track>\n'
127+
128+
for element in rootIn.iterfind("Log/Samples/Sample"):
129+
time = int(element.findtext("Time"))
130+
131+
if (time >= timeslot_start and time <= timeslot_finish):
132+
t_trackpoint = etree.Element('Trackpoint')
133+
t_time = etree.SubElement(t_trackpoint, "Time")
134+
t_position = etree.SubElement(t_trackpoint, "Position")
135+
136+
lat = element.findtext("Latitude")
137+
lon = element.findtext("Longitude")
138+
#time = float(element.findtext("Time")) / 1000.0
139+
time = int(element.findtext("Time")) / 1000 # with float results are incorrect
140+
currentTime = startTime+datetime.timedelta(0, time)
141+
t_time.text = currentTime.isoformat()+"Z"
142+
143+
altitude = element.findtext("Altitude") if element.findtext("Altitude")!=None else altitudeLast
144+
hr = element.findtext("HR") if element.findtext("HR") != None else hrLast
145+
cadence = element.findtext("Cadence") if element.findtext("Cadence") != None else cadenceLast
146+
power = element.findtext("BikePower") if element.findtext("BikePower") != None else powerLast
147+
speed = element.findtext("Speed") if element.findtext("Speed") != None else speedLast
148+
temp = str(float(element.findtext("Temperature"))/10) if element.findtext("Temperature") != None else tempLast
149+
airpressure = element.findtext("SeaLevelPressure") if element.findtext("SeaLevelPressure") != None else airpressureLast
150+
151+
if ((lat != None) and (lon != None)):
152+
t_time
153+
154+
lat = float(lat)/10000000
155+
lon = float(lon)/10000000
156+
157+
t_latitudeDegrees = etree.SubElement(t_position, "LatitudeDegrees")
158+
t_latitudeDegrees.text = str(lat)
159+
t_longitudeDegrees = etree.SubElement(t_position, "LongitudeDegrees")
160+
t_longitudeDegrees.text = str(lon)
161+
162+
latLatest = str(lat)
163+
lonLatest = str(lon)
164+
165+
if (altitude != None):
166+
etree.SubElement(t_trackpoint, "AltitudeMeters").text = altitude
167+
elif (altitudeLast != None):
168+
etree.SubElement(t_trackpoint, "AltitudeMeters").text = altitudeLast
169+
170+
if ((hr != None) or (cadence != None) or (power != None) or (speed != None) or (temp != None) or (airpressure != None)):
171+
t_extGpx = etree.SubElement(t_trackpoint, "Extensions")
172+
t_tpx = etree.SubElement(t_extGpx, "TPX")
173+
t_tpx.set("xmlns", "http://www.garmin.com/xmlschemas/ActivityExtension/v2")
174+
if (hr != None):
175+
etree.SubElement(t_tpx, "HR").text = hr
176+
if (cadence != None):
177+
etree.SubElement(t_tpx, "Cadence").text = cadence
178+
if (power != None):
179+
etree.SubElement(t_tpx, "Power").text = power
180+
if (temp != None):
181+
etree.SubElement(t_tpx, "Temp").text = temp
182+
if (speed != None):
183+
etree.SubElement(t_tpx, "Speed").text = str(float(speed) / 100.0)
184+
if (airpressure != None):
185+
etree.SubElement(t_tpx,"SeaLevelPressure").text = airpressure
186+
187+
out+=" "+etree.tostring(t_trackpoint, pretty_print=True)+"\n"
188+
189+
190+
latLast=lat
191+
lonLast=lon
192+
timeLast=time
193+
altitudeLast=altitude
194+
hrLast=hr
195+
cadenceLast=cadence
196+
powerLast=power
197+
speedLast=speed
198+
tempLast=temp
199+
airpressureLast=airpressure
200+
201+
lat=None
202+
lon=None
203+
time=None
204+
altitude=None
205+
hr=None
206+
cadence=None
207+
power=None
208+
speed=None
209+
temp=None
210+
airpressure=None
211+
212+
out += ' </Track>\n'
213+
out += ' </Lap>\n'
214+
215+
deviceInfo = rootIn.find("DeviceInfo")
216+
deviceName = deviceInfo.findtext("Name")
217+
218+
out += ' <Creator xsi:type="Device_t">\n'
219+
out += ' <Name>' + deviceName + '</Name>\n'
220+
out += ' <UnitId>0</UnitId>\n'
221+
out += ' <ProductID>0</ProductID>\n'
222+
out += ' </Creator>\n'
223+
out += ' </Activity>\n'
224+
out += ' </Activities>\n'
225+
out += '</TrainingCenterDatabase>\n'
226+
227+
fOut.write(out)
228+
fOut.close()
229+
230+
print "Done"

0 commit comments

Comments
 (0)