-
Notifications
You must be signed in to change notification settings - Fork 81
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add openambit to TCX conversion scripts and icon
- Loading branch information
Showing
4 changed files
with
430 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
#!/usr/bin/env python2 | ||
|
||
""" converts the *.log files produced by openambit in ~/.openambit/ to standard TCX format. | ||
usage: ./openambit2tcx.py inputfile outputFile | ||
required dependecies: python{2,3}-dateutil ; python{2,3}-lxml | ||
""" | ||
|
||
#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 | ||
#import xml.etree.ElementTree as etree | ||
from lxml import etree | ||
#import math | ||
import sys | ||
import datetime | ||
from dateutil.parser import parse | ||
import StringIO | ||
|
||
############################## | ||
## getting input parameters ## | ||
############################## | ||
|
||
if len(sys.argv) == 3: | ||
fileIn=sys.argv[1] | ||
fileOut=sys.argv[2] | ||
else: | ||
sys.stderr.write("""\ | ||
Convert Openambit *.log files to standard TCX format | ||
usage: {} inputfile outputfile | ||
Openambit *.log files can normally be found in ~/.openambit/ | ||
""".format(sys.argv[0])) | ||
sys.exit(1) | ||
|
||
########################################### | ||
## setting variables up, starting output ## | ||
########################################### | ||
|
||
fOut = open(fileOut, 'w') | ||
|
||
out ='<?xml version="1.0"?>\n' | ||
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' | ||
out +=' <Activities>\n' | ||
out += ' <Activity Sport="Other">\n' | ||
rootIn = etree.parse(fileIn) | ||
t_time = rootIn.find("Time") | ||
out += ' <Id>' + t_time.text + 'Z</Id>\n' | ||
out += ' <Lap StartTime="' + t_time.text + 'Z">\n' | ||
header = rootIn.find("Log/Header") | ||
duration = header.findtext("Duration") | ||
out += ' <TotalTimeSeconds>' + str(float(duration) / 1000) + '</TotalTimeSeconds>\n' | ||
distance = header.findtext("Distance") | ||
out += ' <DistanceMeters>' + distance + '</DistanceMeters>\n' | ||
header = rootIn.find("Log/Header/Speed") | ||
speedMax = header.findtext("Max") | ||
out += ' <MaximumSpeed>' + str(float(speedMax) / 3600) + '</MaximumSpeed>\n' | ||
# ?Calories is missing from openambit dump files? | ||
out += ' <Track>\n' | ||
|
||
|
||
latLast=None | ||
lonLast=None | ||
timeLast=None | ||
altitudeLast=None | ||
hrLast=None | ||
cadenceLast=None | ||
powerLast=None | ||
speedLast=None | ||
tempLast=None | ||
airpressureLast=None | ||
latLatest=None | ||
lonLatest=None | ||
timeGPSLatest=None | ||
|
||
'''lapCount=0 | ||
lapArray=[0] | ||
maxLap=0''' | ||
|
||
year = parse(t_time.text, fuzzy=True).year | ||
month = parse(t_time.text, fuzzy=True).month | ||
day = parse(t_time.text, fuzzy=True).day | ||
hour = parse(t_time.text, fuzzy=True).hour | ||
minute = parse(t_time.text, fuzzy=True).minute | ||
second = parse(t_time.text, fuzzy=True).second | ||
startTime = datetime.datetime(year, month, day, hour, minute, second) | ||
|
||
########################### | ||
## getting laps data ## | ||
########################### | ||
|
||
intervals = [] | ||
|
||
for element in rootIn.iterfind("Log/Samples/Sample/Lap"): | ||
type_id = element.find('Type').attrib | ||
if type_id['id'] == '1': | ||
datetime_l = element.find('DateTime').text | ||
duration_l = element.find('Duration').text | ||
distance_l = element.find('Distance').text | ||
|
||
intervals.append(element) | ||
|
||
########################### | ||
## getting activity data ## | ||
########################### | ||
|
||
t_activities = etree.Element('Activities') | ||
t_activity = etree.SubElement(t_activities, 'Activity') | ||
t_activity.set('Sport', 'Other') | ||
t_id = etree.SubElement(t_activity, "Id") | ||
t_id.text = t_time.text + 'Z' | ||
|
||
timeslot_finish = 0 | ||
timeslot_start = 0 | ||
|
||
for lap in intervals: | ||
type_id = lap.find('Type').attrib | ||
datetime_l = lap.find('DateTime').text | ||
duration_l = int(lap.find('Duration').text) | ||
distance_l = lap.find('Distance').text | ||
timeslot_start = timeslot_finish + 1 | ||
timeslot_finish += duration_l | ||
|
||
out += ' <Lap StartTime="' + datetime_l + 'Z">\n' | ||
out += ' <TotalTimeSeconds>' + str(float(duration_l) / 1000) + '</TotalTimeSeconds>\n' | ||
out += ' <DistanceMeters>' + distance_l + '</DistanceMeters>\n' | ||
#out += ' <MaximumSpeed>' + "" + '</MaximumSpeed>\n' # not needed in | ||
# ?Calories is missing from openambit dump files? | ||
out += ' <Track>\n' | ||
|
||
for element in rootIn.iterfind("Log/Samples/Sample"): | ||
time = int(element.findtext("Time")) | ||
|
||
if (time >= timeslot_start and time <= timeslot_finish): | ||
t_trackpoint = etree.Element('Trackpoint') | ||
t_time = etree.SubElement(t_trackpoint, "Time") | ||
t_position = etree.SubElement(t_trackpoint, "Position") | ||
|
||
lat = element.findtext("Latitude") | ||
lon = element.findtext("Longitude") | ||
#time = float(element.findtext("Time")) / 1000.0 | ||
time = int(element.findtext("Time")) / 1000 # with float results are incorrect | ||
currentTime = startTime+datetime.timedelta(0, time) | ||
t_time.text = currentTime.isoformat()+"Z" | ||
|
||
altitude = element.findtext("Altitude") if element.findtext("Altitude")!=None else altitudeLast | ||
hr = element.findtext("HR") if element.findtext("HR") != None else hrLast | ||
cadence = element.findtext("Cadence") if element.findtext("Cadence") != None else cadenceLast | ||
power = element.findtext("BikePower") if element.findtext("BikePower") != None else powerLast | ||
speed = element.findtext("Speed") if element.findtext("Speed") != None else speedLast | ||
temp = str(float(element.findtext("Temperature"))/10) if element.findtext("Temperature") != None else tempLast | ||
airpressure = element.findtext("SeaLevelPressure") if element.findtext("SeaLevelPressure") != None else airpressureLast | ||
|
||
if ((lat != None) and (lon != None)): | ||
t_time | ||
|
||
lat = float(lat)/10000000 | ||
lon = float(lon)/10000000 | ||
|
||
t_latitudeDegrees = etree.SubElement(t_position, "LatitudeDegrees") | ||
t_latitudeDegrees.text = str(lat) | ||
t_longitudeDegrees = etree.SubElement(t_position, "LongitudeDegrees") | ||
t_longitudeDegrees.text = str(lon) | ||
|
||
latLatest = str(lat) | ||
lonLatest = str(lon) | ||
|
||
if (altitude != None): | ||
etree.SubElement(t_trackpoint, "AltitudeMeters").text = altitude | ||
elif (altitudeLast != None): | ||
etree.SubElement(t_trackpoint, "AltitudeMeters").text = altitudeLast | ||
|
||
if ((hr != None) or (cadence != None) or (power != None) or (speed != None) or (temp != None) or (airpressure != None)): | ||
t_extGpx = etree.SubElement(t_trackpoint, "Extensions") | ||
t_tpx = etree.SubElement(t_extGpx, "TPX") | ||
t_tpx.set("xmlns", "http://www.garmin.com/xmlschemas/ActivityExtension/v2") | ||
if (hr != None): | ||
etree.SubElement(t_tpx, "HR").text = hr | ||
if (cadence != None): | ||
etree.SubElement(t_tpx, "Cadence").text = cadence | ||
if (power != None): | ||
etree.SubElement(t_tpx, "Power").text = power | ||
if (temp != None): | ||
etree.SubElement(t_tpx, "Temp").text = temp | ||
if (speed != None): | ||
etree.SubElement(t_tpx, "Speed").text = str(float(speed) / 100.0) | ||
if (airpressure != None): | ||
etree.SubElement(t_tpx,"SeaLevelPressure").text = airpressure | ||
|
||
out+=" "+etree.tostring(t_trackpoint, pretty_print=True)+"\n" | ||
|
||
|
||
latLast=lat | ||
lonLast=lon | ||
timeLast=time | ||
altitudeLast=altitude | ||
hrLast=hr | ||
cadenceLast=cadence | ||
powerLast=power | ||
speedLast=speed | ||
tempLast=temp | ||
airpressureLast=airpressure | ||
|
||
lat=None | ||
lon=None | ||
time=None | ||
altitude=None | ||
hr=None | ||
cadence=None | ||
power=None | ||
speed=None | ||
temp=None | ||
airpressure=None | ||
|
||
out += ' </Track>\n' | ||
out += ' </Lap>\n' | ||
|
||
deviceInfo = rootIn.find("DeviceInfo") | ||
deviceName = deviceInfo.findtext("Name") | ||
|
||
out += ' <Creator xsi:type="Device_t">\n' | ||
out += ' <Name>' + deviceName + '</Name>\n' | ||
out += ' <UnitId>0</UnitId>\n' | ||
out += ' <ProductID>0</ProductID>\n' | ||
out += ' </Creator>\n' | ||
out += ' </Activity>\n' | ||
out += ' </Activities>\n' | ||
out += '</TrainingCenterDatabase>\n' | ||
|
||
fOut.write(out) | ||
fOut.close() | ||
|
||
print "Done" |
Oops, something went wrong.