diff --git a/icon.png b/icon.png new file mode 100644 index 00000000..f717e1bc Binary files /dev/null and b/icon.png differ diff --git a/tools/openambit2gpx.py b/tools/openambit2gpx.py old mode 100644 new mode 100755 diff --git a/tools/openambit2tcx-lap.py b/tools/openambit2tcx-lap.py new file mode 100755 index 00000000..60328fc4 --- /dev/null +++ b/tools/openambit2tcx-lap.py @@ -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 ='\n' +out += '\n' +out +=' \n' +out += ' \n' +rootIn = etree.parse(fileIn) +t_time = rootIn.find("Time") +out += ' ' + t_time.text + 'Z\n' +out += ' \n' +header = rootIn.find("Log/Header") +duration = header.findtext("Duration") +out += ' ' + str(float(duration) / 1000) + '\n' +distance = header.findtext("Distance") +out += ' ' + distance + '\n' +header = rootIn.find("Log/Header/Speed") +speedMax = header.findtext("Max") +out += ' ' + str(float(speedMax) / 3600) + '\n' +# ?Calories is missing from openambit dump files? +out += ' \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 += ' \n' + out += ' ' + str(float(duration_l) / 1000) + '\n' + out += ' ' + distance_l + '\n' + #out += ' ' + "" + '\n' # not needed in + # ?Calories is missing from openambit dump files? + out += ' \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 += ' \n' + out += ' \n' + +deviceInfo = rootIn.find("DeviceInfo") +deviceName = deviceInfo.findtext("Name") + +out += ' \n' +out += ' ' + deviceName + '\n' +out += ' 0\n' +out += ' 0\n' +out += ' \n' +out += ' \n' +out += ' \n' +out += '\n' + +fOut.write(out) +fOut.close() + +print "Done" diff --git a/tools/openambit2tcx-nolap.py b/tools/openambit2tcx-nolap.py new file mode 100755 index 00000000..734c6382 --- /dev/null +++ b/tools/openambit2tcx-nolap.py @@ -0,0 +1,200 @@ +#!/usr/bin/python + +""" converts the *.log files produced by openambit in ~/.openambit/ to standard TCX format. +usage: ./openambit2tcx.py inputfile outputFile +required dependecies: python{2,3}-dateutil +""" + +#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 +import math +import sys +import datetime +from dateutil.parser import parse + +############################## +## 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='\n\n' +out+='\n' +out+=' \n' +out+=' \n' + +rootIn=etree.parse(fileIn) +t_time = rootIn.find("Time") +out+=' ' + t_time.text + 'Z\n' +out+=' \n' + +header = rootIn.find("Log/Header") +duration = header.findtext("Duration") +out+=' ' + str(float(duration) / 1000) + '\n' +distance = header.findtext("Distance") +out+=' ' + distance + '\n' +header = rootIn.find("Log/Header/Speed") +speedMax = header.findtext("Max") +out+=' ' + str(float(speedMax) / 3600) + '\n' +# ?Calories is missing from openambit dump files? +out+=' \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 +#print (str(year) + "\n" + str(month) + "\n" + str(day) + "\n" + str(hour) + "\n" + str(minute) + "\n" + str(second) + "\n") + +startTime = datetime.datetime(year, month, day, hour, minute, second) + +########################### +## getting activity data ## +########################### + +for element in rootIn.iterfind("Log/Samples/Sample"): + 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 + 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 + + sampType=element.findtext("Type") + if sampType=="lap-info": + lapType=element.findtext("Lap/Type") + lapDate=element.findtext("Lap/DateTime") + lapDuration=element.findtext("Lap/Duration") + lapDistance=element.findtext("Lap/Distance") + lapUtc=element.findtext("UTC") + lapPreviousLat=latLatest + lapPreviousLon=lonLatest + lapPreviousTime=timeGPSLatest + lapCheck=1 + + if lapCount==0: + lapArray[0]=[lapType,lapDate,lapDuration,lapDistance,lapUtc,lapPreviousLat,lapPreviousLon,lapPreviousTime,0,0,0] + else: + lapArray.append([lapType,lapDate,lapDuration,lapDistance,lapUtc,lapPreviousLat,lapPreviousLon,lapPreviousTime,0,0,0]) + lapCount+=1 + + maxLap=lapCount-1 + + 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 lapCheck==1: + lapArray[lapCount-1][8]=latLatest + lapArray[lapCount-1][9]=lonLatest + lapArray[lapCount-1][10]=timeGPSLatest + lapCheck=0 + + 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 + + if altitude!=None: + out+=" "+etree.tostring(t_trackpoint)+"\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+=' \n' +out+=' \n' +out+=' \n' +out+=' \n' +out+='\n' + +fOut.write(out) + +fOut.close()