You can subscribe to this list here.
2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2009 |
Jan
|
Feb
(1) |
Mar
(15) |
Apr
(20) |
May
(2) |
Jun
(9) |
Jul
(3) |
Aug
(2) |
Sep
(17) |
Oct
(16) |
Nov
(38) |
Dec
(40) |
2010 |
Jan
(51) |
Feb
(11) |
Mar
(24) |
Apr
(31) |
May
(24) |
Jun
(3) |
Jul
(9) |
Aug
(1) |
Sep
(29) |
Oct
(33) |
Nov
(81) |
Dec
(6) |
2011 |
Jan
(2) |
Feb
(4) |
Mar
(13) |
Apr
(4) |
May
(24) |
Jun
(4) |
Jul
(19) |
Aug
(46) |
Sep
(10) |
Oct
(28) |
Nov
(31) |
Dec
|
From: <jb...@us...> - 2009-10-19 09:42:01
|
Revision: 368 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=368&view=rev Author: jblance Date: 2009-10-19 09:41:47 +0000 (Mon, 19 Oct 2009) Log Message: ----------- Added tmp dir clean up on start to plugins-v2 branch Modified Paths: -------------- pytrainer/branches/plugins-v2/pytrainer/lib/system.py pytrainer/branches/plugins-v2/pytrainer/main.py Modified: pytrainer/branches/plugins-v2/pytrainer/lib/system.py =================================================================== --- pytrainer/branches/plugins-v2/pytrainer/lib/system.py 2009-10-15 09:30:33 UTC (rev 367) +++ pytrainer/branches/plugins-v2/pytrainer/lib/system.py 2009-10-19 09:41:47 UTC (rev 368) @@ -25,7 +25,7 @@ self.tmpdir = None self.confdir = None self.conffile = None - self.gpxdir = None + self.gpxdir = None self.extensiondir = None self.plugindir = None @@ -36,48 +36,60 @@ self._setPluginDir() self._setGpxDir() - def _setHome(self): - if sys.platform == "linux2": - variable = 'HOME' - elif sys.platform == "win32": + def _setHome(self): + if sys.platform == "linux2": + variable = 'HOME' + elif sys.platform == "win32": variable = 'USERPROFILE' + else: + print "Unsupported sys.platform: %s." % sys.platform + sys.exit(1) + self.home = os.environ[variable] + + def _setTempDir(self): + self.tmpdir = self.confdir+"/tmp" + if not os.path.isdir(self.tmpdir): + os.mkdir(self.tmpdir) - self.home = os.environ[variable] - - def _setTempDir(self): - if sys.platform == "win32": - self.tmpdir = "C:/backup" - elif sys.platform == "linux2": - self.tmpdir = self.confdir+"/tmp" - - if not os.path.isdir(self.tmpdir): - os.mkdir(self.tmpdir) - - def _setConfFiles(self): - if sys.platform == "win32": - self.confdir = self.home+"/pytrainer" - self.conffile = self.confdir+"/conf.xml" - elif sys.platform == "linux2": - self.confdir = self.home+"/.pytrainer" - self.conffile = self.confdir+"/conf.xml" - + def clearTempDir(self): + """Function to clear out the tmp directory that pytrainer uses + will only remove files + """ + if not os.path.isdir(self.tmpdir): + return + else: + files = os.listdir(self.tmpdir) + for name in files: + fullname = (os.path.join(self.tmpdir, name)) + if os.path.isfile(fullname): + os.remove(os.path.join(self.tmpdir, name)) + + def _setConfFiles(self): + if sys.platform == "win32": + self.confdir = self.home+"/pytrainer" + elif sys.platform == "linux2": + self.confdir = self.home+"/.pytrainer" + else: + print "Unsupported sys.platform: %s." % sys.platform + sys.exit(1) + self.conffile = self.confdir+"/conf.xml" if not os.path.isdir(self.confdir): - os.mkdir(self.confdir) + os.mkdir(self.confdir) def _setGpxDir(self): - self.gpxdir = self.confdir+"/gpx" + self.gpxdir = self.confdir+"/gpx" if not os.path.isdir(self.gpxdir): - os.mkdir(self.gpxdir) + os.mkdir(self.gpxdir) def _setExtensionDir(self): - self.extensiondir = self.confdir+"/extensions" + self.extensiondir = self.confdir+"/extensions" if not os.path.isdir(self.extensiondir): - os.mkdir(self.extensiondir) + os.mkdir(self.extensiondir) def _setPluginDir(self): - self.plugindir = self.confdir+"/plugins" + self.plugindir = self.confdir+"/plugins" if not os.path.isdir(self.plugindir): - os.mkdir(self.plugindir) + os.mkdir(self.plugindir) def getConfFile(self): if not os.path.isfile(self.conffile): @@ -88,4 +100,3 @@ def getValue(self,variable): method = getattr(self, variable) return method - Modified: pytrainer/branches/plugins-v2/pytrainer/main.py =================================================================== --- pytrainer/branches/plugins-v2/pytrainer/main.py 2009-10-15 09:30:33 UTC (rev 367) +++ pytrainer/branches/plugins-v2/pytrainer/main.py 2009-10-19 09:41:47 UTC (rev 368) @@ -105,6 +105,8 @@ logging.debug('checking configuration...') self.conf = checkConf() + logging.debug("clearing tmp directory %s" % self.conf.getValue("tmpdir")) + self.conf.clearTempDir() self.filename = self.conf.getValue("conffile") logging.debug('retrieving data from '+ self.filename) self.configuration = XMLParser(self.filename) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-10-15 09:30:43
|
Revision: 367 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=367&view=rev Author: jblance Date: 2009-10-15 09:30:33 +0000 (Thu, 15 Oct 2009) Log Message: ----------- Change tmpdir to be user specific for linux (in plugins branch) Modified Paths: -------------- pytrainer/branches/plugins-v2/pytrainer/lib/system.py Modified: pytrainer/branches/plugins-v2/pytrainer/lib/system.py =================================================================== --- pytrainer/branches/plugins-v2/pytrainer/lib/system.py 2009-10-13 09:47:40 UTC (rev 366) +++ pytrainer/branches/plugins-v2/pytrainer/lib/system.py 2009-10-15 09:30:33 UTC (rev 367) @@ -30,8 +30,8 @@ self.plugindir = None self._setHome() + self._setConfFiles() self._setTempDir() - self._setConfFiles() self._setExtensionDir() self._setPluginDir() self._setGpxDir() @@ -48,7 +48,7 @@ if sys.platform == "win32": self.tmpdir = "C:/backup" elif sys.platform == "linux2": - self.tmpdir = "/tmp/virtual_dir" + self.tmpdir = self.confdir+"/tmp" if not os.path.isdir(self.tmpdir): os.mkdir(self.tmpdir) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-10-13 09:47:51
|
Revision: 366 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=366&view=rev Author: jblance Date: 2009-10-13 09:47:40 +0000 (Tue, 13 Oct 2009) Log Message: ----------- Fixed HR for Garmin-HR in plugins branch Modified Paths: -------------- pytrainer/branches/plugins-v2/plugins/garmin-hr/translate.xsl pytrainer/branches/plugins-v2/plugins/garmin-hr-file/translate.xsl Modified: pytrainer/branches/plugins-v2/plugins/garmin-hr/translate.xsl =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr/translate.xsl 2009-10-12 07:34:20 UTC (rev 365) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr/translate.xsl 2009-10-13 09:47:40 UTC (rev 366) @@ -41,9 +41,9 @@ <trkpt lat="{$lat}" lon="{$lon}"><xsl:value-of select="$newline"/> <ele><xsl:value-of select="t:AltitudeMeters"/></ele><xsl:value-of select="$newline"/> <time><xsl:value-of select="t:Time"/></time><xsl:value-of select="$newline"/> - <xsl:if test="t:HeartRateBpm/t:Value"> + <xsl:if test="t:HeartRateBpm"> <extensions><xsl:value-of select="$newline"/> - <gpxdata:hr><xsl:value-of select="t:HeartRateBpm/t:Value"/></gpxdata:hr><xsl:value-of select="$newline"/> + <gpxdata:hr><xsl:value-of select="t:HeartRateBpm"/></gpxdata:hr><xsl:value-of select="$newline"/> </extensions><xsl:value-of select="$newline"/> </xsl:if> </trkpt><xsl:value-of select="$newline"/> Modified: pytrainer/branches/plugins-v2/plugins/garmin-hr-file/translate.xsl =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr-file/translate.xsl 2009-10-12 07:34:20 UTC (rev 365) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr-file/translate.xsl 2009-10-13 09:47:40 UTC (rev 366) @@ -41,9 +41,9 @@ <trkpt lat="{$lat}" lon="{$lon}"><xsl:value-of select="$newline"/> <ele><xsl:value-of select="t:AltitudeMeters"/></ele><xsl:value-of select="$newline"/> <time><xsl:value-of select="t:Time"/></time><xsl:value-of select="$newline"/> - <xsl:if test="t:HeartRateBpm/t:Value"> + <xsl:if test="t:HeartRateBpm"> <extensions><xsl:value-of select="$newline"/> - <gpxdata:hr><xsl:value-of select="t:HeartRateBpm/t:Value"/></gpxdata:hr><xsl:value-of select="$newline"/> + <gpxdata:hr><xsl:value-of select="t:HeartRateBpm"/></gpxdata:hr><xsl:value-of select="$newline"/> </extensions><xsl:value-of select="$newline"/> </xsl:if> </trkpt><xsl:value-of select="$newline"/> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-10-12 07:34:30
|
Revision: 365 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=365&view=rev Author: jblance Date: 2009-10-12 07:34:20 +0000 (Mon, 12 Oct 2009) Log Message: ----------- Update to garmin-hr in plugin branch Modified Paths: -------------- pytrainer/branches/plugins-v2/plugins/garmin-hr/conf.xml Added Paths: ----------- pytrainer/branches/plugins-v2/plugins/garmin-hr/garminhr.py pytrainer/branches/plugins-v2/plugins/garmin-hr/translate.xsl Removed Paths: ------------- pytrainer/branches/plugins-v2/plugins/garmin-hr/gtrnctr2gpx.py pytrainer/branches/plugins-v2/plugins/garmin-hr/main.py Modified: pytrainer/branches/plugins-v2/plugins/garmin-hr/conf.xml =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr/conf.xml 2009-10-11 08:31:03 UTC (rev 364) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr/conf.xml 2009-10-12 07:34:20 UTC (rev 365) @@ -2,9 +2,9 @@ <pytrainer-plugin name="Garmin Heart Rate" description="Import yor records direclty from your garmin gps device with heart rate support" - plugincode="garmin-hr" + plugincode="garminhr" pluginbutton="Import from Garmin (HR support)" - executable="main.py" + executable="garminhr" > <conf-values variable="device" value="usb:"/> </pytrainer-plugin> Added: pytrainer/branches/plugins-v2/plugins/garmin-hr/garminhr.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr/garminhr.py (rev 0) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr/garminhr.py 2009-10-12 07:34:20 UTC (rev 365) @@ -0,0 +1,133 @@ +#!/usr/bin/python +# -*- coding: iso-8859-1 -*- + +#Copyright (C) Fiz Vazquez vu...@si... + +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either version 2 +#of the License, or (at your option) any later version. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. + +#You should have received a copy of the GNU General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import os, sys +import logging +from lxml import etree + +import commands + +class garminhr(): + """ Plugin to import from a Garmin device using gpsbabel + Checks each activity to see if any entries are in the database with the same start time + Creates GPX files for each activity not in the database + + Note: using lxml see http://codespeak.net/lxml + """ + def __init__(self, parent = None, validate=False): + self.parent = parent + self.tmpdir = self.parent.conf.getValue("tmpdir") + self.data_path = os.path.dirname(__file__) + self.validate = validate + self.input_dev = None + + def run(self): + logging.debug(">>") + importfiles = [] + if self.garminDeviceExists(): + try: + gpsbabelOutputFile = "%s/file.gtrnctr" % (self.tmpdir) + testInputFile = "/home/johnb/garmin/2009.07.26\ 143201.TCX" + #TODO Remove Zenity below + outgps = commands.getstatusoutput("gpsbabel -t -i garmin -f %s -o gtrnctr -F %s | zenity --progress --pulsate --text='Loading Data' auto-close" % (self.input_dev, gpsbabelOutputFile) ) + if outgps[0]==0: + if outgps[1] == "Found no Garmin USB devices.": # check localizations + print "GPSBabel found no Garmin USB devices" + pass + else: #gpsbabel worked - now process file... + if self.valid_input_file(gpsbabelOutputFile): + tracks = self.getTracks(gpsbabelOutputFile) + logging.debug("Found %d tracks in %s" % (len(tracks), gpsbabelOutputFile)) + for track in tracks: #can be multiple tracks + if self.shouldImport(track): + gpxfile = "%s/garminhrfile%d.gpx" % (self.tmpdir, len(importfiles)) + self.createGPXfile(gpxfile, track) + importfiles.append(gpxfile) + logging.debug("Importing %s of %s tracks" % (len(importfiles), len(tracks)) ) + else: + logging.info("File %s failed validation" % (gpsbabelOutputFile)) + except Exception: + #TODO Remove Zenity below + os.popen("zenity --error --text='Can not handle Garmin device\nCheck your configuration\nCurrent usb port is set to:\t %s'" %self.input_dev); + print sys.exc_info()[0] + else: #No garmin device found + #TODO Remove Zenity below + os.popen("zenity --error --text='Can not handle Garmin device\nCheck your configuration\nCurrent usb port is set to:\t %s'" %self.input_dev); + logging.debug("<<") + return importfiles + + + def garminDeviceExists(self): + try: + outmod = commands.getstatusoutput('/sbin/lsmod | grep garmin_gps') + if outmod[0]==256: #there is no garmin_gps module loaded + self.input_dev = "usb:" + return True + else: + return False + except: + return False + + def valid_input_file(self, filename): + """ Function to validate input file if requested""" + if not self.validate: #not asked to validate + logging.debug("Not validating %s" % (filename) ) + return True + else: #Validate TCXv1, note are validating against gpsbabels 'broken' result... + xslfile = os.path.realpath(self.parent.parent.data_path)+ "/schemas/GarminTrainingCenterDatabase_v1-gpsbabel.xsd" + from lib.xmlValidation import xmlValidator + validator = xmlValidator() + return validator.validateXSL(filename, xslfile) + + def getTracks(self, filename): + """ Function to return all the tracks in a Garmin Training Center v1 file + """ + tree = etree.ElementTree(file=filename) + root = tree.getroot() + tracks = root.findall(".//{http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v1}Track") + return tracks + + def shouldImport(self, track): + """ Function determines whether a track should be imported or not + Currently using time only + """ + timeElement = track.find(".//{http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v1}Time") + if timeElement is None: + #print (etree.tostring(track, pretty_print=True)) + logging.debug("Error no time found in track") + return False + else: + time = timeElement.text + #comparing date and start time (sport may have been changed in DB after import) + if self.parent.parent.ddbb.select("records","*","date_time_utc=\"%s\"" % (time)): + logging.debug("Not importing track for time %s" % (time)) + return False + else: + return True + + def createGPXfile(self, gpxfile, track): + """ Function to transform a Garmin Training Center v1 Track to a valid GPX+ file + """ + xslt_doc = etree.parse(self.data_path+"/translate.xsl") + transform = etree.XSLT(xslt_doc) + result_tree = transform(track) + result_tree.write(gpxfile) + + + Deleted: pytrainer/branches/plugins-v2/plugins/garmin-hr/gtrnctr2gpx.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr/gtrnctr2gpx.py 2009-10-11 08:31:03 UTC (rev 364) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr/gtrnctr2gpx.py 2009-10-12 07:34:20 UTC (rev 365) @@ -1,82 +0,0 @@ -#!/usr/bin/python -# -*- coding: iso-8859-1 -*- - -#Copyright (C) Fiz Vazquez vu...@si... - -#This program is free software; you can redistribute it and/or -#modify it under the terms of the GNU General Public License -#as published by the Free Software Foundation; either version 2 -#of the License, or (at your option) any later version. - -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. - -#You should have received a copy of the GNU General Public License -#along with this program; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - -import sys - -import xml.dom.minidom - -#the _variables are the gpx ones. The variables are the xcsv one - - -def gtrnctr2gpx(gtrnctrfile,gpxfile): - dom = xml.dom.minidom.parse(gtrnctrfile) - d = xml.dom.minidom.getDOMImplementation() - _dom = d.createDocument(None,"gpx",None) - _gpx_element = _dom.documentElement - _gpx_element.setAttribute('creator',"pytrainer http://pytrainer.e-oss.net") - _gpx_element.setAttribute('version',"1.1") - _gpx_element.setAttribute('xmlns',"http://www.topografix.com/GPX/1/1") - _gpx_element.setAttribute('xmlns:geocache',"http://www.groundspeak.com/cache/1/0") - _gpx_element.setAttribute('xmlns:gpxdata',"http://www.cluetrust.com/XML/GPXDATA/1/0") - _gpx_element.setAttribute('xmlns:xsi',"http://www.w3.org/2001/XMLSchema-instance") - _gpx_element.setAttribute('xsi:schemaLocation',"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.cluetrust.com/XML/GPXDATA/1/0 http://www.cluetrust.com/Schemas/gpxdata10.xsd") - - trks = dom.getElementsByTagName("Track") - nametrack = 0 - for trk in trks: - nametrack = nametrack+1 - _trk = _dom.createElement("trk") - _name = _dom.createElement("name") - _name.appendChild(_dom.createTextNode("%s"%str(nametrack))) - _trk.appendChild(_name) - trkpoints = trk.getElementsByTagName("Trackpoint") - for trkpoint in trkpoints: - _trkpt = _dom.createElement("trkpt") - time = trkpoint.getElementsByTagName("Time")[0].firstChild.data - alt = trkpoint.getElementsByTagName("AltitudeMeters")[0].firstChild.data - if len(trkpoint.getElementsByTagName("HeartRateBpm"))>0: - hr = trkpoint.getElementsByTagName("HeartRateBpm")[0].firstChild.data - else: - hr = "0" - lat = trkpoint.getElementsByTagName("LatitudeDegrees")[0].firstChild.data - lon = trkpoint.getElementsByTagName("LongitudeDegrees")[0].firstChild.data - - _time = _dom.createElement("time") - _ele = _dom.createElement("ele") - _hr = _dom.createElement("gpxdata:hr") - _extensions = _dom.createElement("extensions") - _time.appendChild(_dom.createTextNode(time)) - _ele.appendChild(_dom.createTextNode(alt)) - _hr.appendChild(_dom.createTextNode(hr)) - _extensions.appendChild(_hr) - _trkpt.appendChild(_time) - _trkpt.appendChild(_ele) - _trkpt.appendChild(_extensions) - _trkpt.setAttribute('lat', lat) - _trkpt.setAttribute('lon', lon) - _trk.appendChild(_trkpt) - _gpx_element.appendChild(_trk) - - f = open(gpxfile, 'w') - #_dom.writexml(f) - #f.write(_dom.toprettyxml()) - f.write(_dom.toxml()) - f.close() - Deleted: pytrainer/branches/plugins-v2/plugins/garmin-hr/main.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr/main.py 2009-10-11 08:31:03 UTC (rev 364) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr/main.py 2009-10-12 07:34:20 UTC (rev 365) @@ -1,63 +0,0 @@ -#!/usr/bin/python -# -*- coding: iso-8859-1 -*- - -#Copyright (C) Fiz Vazquez vu...@si... - -#This program is free software; you can redistribute it and/or -#modify it under the terms of the GNU General Public License -#as published by the Free Software Foundation; either version 2 -#of the License, or (at your option) any later version. - -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. - -#You should have received a copy of the GNU General Public License -#along with this program; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - -from optparse import OptionParser -#from gtrnctr2gpx import gtrnctr2gpx -import os -import commands - -parser = OptionParser() -parser.add_option("-d", "--device", dest="device") -(options,args) = parser.parse_args() -gtrnctrFile="/tmp/file.gtrnctr" -gtrnctrFileMod="/tmp/file_mod.gtrnctr" -input_dev = options.device - -# ToDo (19.05.2008): better exception handling -try: - outmod = commands.getstatusoutput('/sbin/lsmod | grep garmin_gps') - #os.popen("zenity --error --text='Devuelve: %s'" %str(outmod)) - if outmod[0]==256: #there is no garmin_gps module loaded - input_dev = "usb:" - else: - raise Exception - # Can't export to GPX directly because lack of support for heartrate and sports (1.0 version, may change when gpsbabel supports 1.1 with custom fields) - outgps = commands.getstatusoutput("gpsbabel -t -i garmin -f %s -o gtrnctr -F /tmp/file.gtrnctr | zenity --progress --pulsate --text='Loading Data' auto-close" %input_dev) - #os.popen("zenity --error --text='Devuelve: %s'" %str(outgps)) - # XML file from gpsbabel refers to schemas and namespace definitions which are no longer available, removing this info - dgg - 12.05.2008 - if outgps[0]==0: - if outgps[1] == "Found no Garmin USB devices.": # check localizations - raise Exception - else: - if os.path.isfile(gtrnctrFile): - f = open(gtrnctrFile,"r") - lines = f.readlines() - f.close() - f = open(gtrnctrFileMod,'w') - headers = lines[0]+'<TrainingCenterDatabase>\n' - f.write(headers) - f.write(''.join(lines[6:])) - f.close() - print gtrnctrFileMod - else: - raise Exception -except Exception: - os.popen("zenity --error --text='Can not handle Garmin device\nCheck your configuration\nCurrent usb port is set to:\t %s'" %input_dev); - Added: pytrainer/branches/plugins-v2/plugins/garmin-hr/translate.xsl =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr/translate.xsl (rev 0) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr/translate.xsl 2009-10-12 07:34:20 UTC (rev 365) @@ -0,0 +1,58 @@ +<?xml version="1.0"?> + +<!-- note defining a namespace for TrainingCenterDatabase as the translation does not seem to work with a default namespace --> +<xsl:stylesheet version="1.0" +xmlns:t="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v1" +xmlns:xsl="http://www.w3.org/1999/XSL/Transform" +> +<xsl:output method="xml" indent="yes" omit-xml-declaration="no"/> + +<!-- this is a bit of a messy way to get whitespace into the output - but it works --> +<xsl:variable name="newline"><xsl:text> +</xsl:text></xsl:variable> + +<xsl:template match="/"> + <gpx xmlns="http://www.topografix.com/GPX/1/1" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:gpxdata="http://www.cluetrust.com/XML/GPXDATA/1/0" + creator="pytrainer http://sourceforge.net/projects/pytrainer" version="1.1" + xsi:schemaLocation="http://www.topografix.com/GPX/1/1 + http://www.topografix.com/GPX/1/1/gpx.xsd + http://www.cluetrust.com/XML/GPXDATA/1/0 + http://www.cluetrust.com/Schemas/gpxdata10.xsd"> + + <xsl:value-of select="$newline"/> + <xsl:variable name="sport">"Run"</xsl:variable> + <xsl:variable name="time"><xsl:value-of select="t:Track/t:Trackpoint/t:Time"/></xsl:variable> + <xsl:variable name="name"><xsl:value-of select="$sport"/><xsl:value-of select="substring($time, 1,10)"/></xsl:variable> + <metadata><xsl:value-of select="$newline"/> + <name><xsl:value-of select="$name"/></name><xsl:value-of select="$newline"/> + <link href="http://sourceforge.net/projects/pytrainer"/><xsl:value-of select="$newline"/> + <time><xsl:value-of select="$time"/></time><xsl:value-of select="$newline"/> + </metadata><xsl:value-of select="$newline"/> + <trk><xsl:value-of select="$newline"/> + <xsl:for-each select="t:Track"> + <trkseg><xsl:value-of select="$newline"/> + <xsl:for-each select="t:Trackpoint"> + <!-- only output a trkpt if a position exists --> + <xsl:if test="t:Position"> + <xsl:variable name="lat"><xsl:value-of select="t:Position/t:LatitudeDegrees"/></xsl:variable> + <xsl:variable name="lon"><xsl:value-of select="t:Position/t:LongitudeDegrees"/></xsl:variable> + <trkpt lat="{$lat}" lon="{$lon}"><xsl:value-of select="$newline"/> + <ele><xsl:value-of select="t:AltitudeMeters"/></ele><xsl:value-of select="$newline"/> + <time><xsl:value-of select="t:Time"/></time><xsl:value-of select="$newline"/> + <xsl:if test="t:HeartRateBpm/t:Value"> + <extensions><xsl:value-of select="$newline"/> + <gpxdata:hr><xsl:value-of select="t:HeartRateBpm/t:Value"/></gpxdata:hr><xsl:value-of select="$newline"/> + </extensions><xsl:value-of select="$newline"/> + </xsl:if> + </trkpt><xsl:value-of select="$newline"/> + </xsl:if> + </xsl:for-each> + <xsl:value-of select="$newline"/> + </trkseg><xsl:value-of select="$newline"/> + </xsl:for-each> + </trk><xsl:value-of select="$newline"/> + </gpx><xsl:value-of select="$newline"/> +</xsl:template> +</xsl:stylesheet> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-10-11 08:31:09
|
Revision: 364 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=364&view=rev Author: jblance Date: 2009-10-11 08:31:03 +0000 (Sun, 11 Oct 2009) Log Message: ----------- Fix so zero speed or maxspeed does not crash pytrainer (in plugins branch) Modified Paths: -------------- pytrainer/branches/plugins-v2/pytrainer/record.py Modified: pytrainer/branches/plugins-v2/pytrainer/record.py =================================================================== --- pytrainer/branches/plugins-v2/pytrainer/record.py 2009-10-11 08:22:55 UTC (rev 363) +++ pytrainer/branches/plugins-v2/pytrainer/record.py 2009-10-11 08:31:03 UTC (rev 364) @@ -189,8 +189,14 @@ summaryRecord['rcd_title'] = '' summaryRecord['rcd_time'] = time_hhmmss #ToDo: makes no sense to work with arrays summaryRecord['rcd_distance'] = "%0.2f" %distance - summaryRecord['rcd_pace'] = "%d.%02d" %((3600/speed)/60,(3600/speed)%60) - summaryRecord['rcd_maxpace'] = "%d.%02d" %((3600/maxspeed)/60,(3600/maxspeed)%60) + if speed == 0: + summaryRecord['rcd_pace'] = 0 + else: + summaryRecord['rcd_pace'] = "%d.%02d" %((3600/speed)/60,(3600/speed)%60) + if maxspeed == 0: + summaryRecord['rcd_maxpace'] = 0 + else: + summaryRecord['rcd_maxpace'] = "%d.%02d" %((3600/maxspeed)/60,(3600/maxspeed)%60) summaryRecord['rcd_average'] = speed summaryRecord['rcd_maxvel'] = maxspeed summaryRecord['rcd_beats'] = gpx.getHeartRateAverage() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-10-11 08:23:04
|
Revision: 363 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=363&view=rev Author: jblance Date: 2009-10-11 08:22:55 +0000 (Sun, 11 Oct 2009) Log Message: ----------- Added support for command line option --valid to plugins branch Modified Paths: -------------- pytrainer/branches/plugins-v2/plugins/garmin-gpx/garmingpx.py pytrainer/branches/plugins-v2/plugins/garmin-hr-file/garminhrfile.py pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/garmin-tcxv2.py pytrainer/branches/plugins-v2/pytrainer/lib/xmlValidation.py pytrainer/branches/plugins-v2/pytrainer/main.py pytrainer/branches/plugins-v2/pytrainer/plugins.py pytrainer/branches/plugins-v2/pytrainer.sh Modified: pytrainer/branches/plugins-v2/plugins/garmin-gpx/garmingpx.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-gpx/garmingpx.py 2009-10-10 00:16:17 UTC (rev 362) +++ pytrainer/branches/plugins-v2/plugins/garmin-gpx/garmingpx.py 2009-10-11 08:22:55 UTC (rev 363) @@ -45,14 +45,14 @@ else: logging.debug("%s already in database. Skipping import." % (filename) ) else: - logging.debug("Invalid input file %s" % (filename)) + logging.info("File %s failed validation" % (filename)) logging.debug("<<") return importfiles def valid_input_file(self, filename): """ Function to validate input file if requested""" - if not self.validate: - #not asked to validate + if not self.validate: #not asked to validate + logging.debug("Not validating %s" % (filename) ) return True else: #To validate GPX as used for pytrainer must test against both Topograpfix and Cluetrust Modified: pytrainer/branches/plugins-v2/plugins/garmin-hr-file/garminhrfile.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr-file/garminhrfile.py 2009-10-10 00:16:17 UTC (rev 362) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr-file/garminhrfile.py 2009-10-11 08:22:55 UTC (rev 363) @@ -58,13 +58,14 @@ importfiles.append(gpxfile) logging.debug("Importing %s of %s tracks" % (len(importfiles), len(tracks)) ) else: - logging.debug("Invalid input file %s" % (filename)) + logging.info("File %s failed validation" % (filename)) logging.debug("<<") return importfiles def valid_input_file(self, filename): """ Function to validate input file if requested""" if not self.validate: #not asked to validate + logging.debug("Not validating %s" % (filename) ) return True else: #Validate TCXv1, note are validating against gpsbabels 'broken' result... xslfile = os.path.realpath(self.parent.parent.data_path)+ "/schemas/GarminTrainingCenterDatabase_v1-gpsbabel.xsd" Modified: pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/garmin-tcxv2.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/garmin-tcxv2.py 2009-10-10 00:16:17 UTC (rev 362) +++ pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/garmin-tcxv2.py 2009-10-11 08:22:55 UTC (rev 363) @@ -47,14 +47,14 @@ else: logging.debug("%s already in database. Skipping import." % (filename,) ) else: - logging.debug("Invalid input file %s" % (filename)) + logging.info("File %s failed validation" % (filename)) logging.debug("<<") return importfiles def valid_input_file(self, filename): """ Function to validate input file if requested""" - if not self.validate: - #not asked to validate + if not self.validate: #not asked to validate + logging.debug("Not validating %s" % (filename) ) return True else: xslfile = os.path.realpath(self.parent.parent.data_path)+ "/schemas/GarminTrainingCenterDatabase_v2.xsd" Modified: pytrainer/branches/plugins-v2/pytrainer/lib/xmlValidation.py =================================================================== --- pytrainer/branches/plugins-v2/pytrainer/lib/xmlValidation.py 2009-10-10 00:16:17 UTC (rev 362) +++ pytrainer/branches/plugins-v2/pytrainer/lib/xmlValidation.py 2009-10-11 08:22:55 UTC (rev 363) @@ -26,13 +26,13 @@ xsl_doc = etree.parse(xslfile) xsl = etree.XMLSchema(xsl_doc) except: - logging.debug("Error attempting to parse %s or %s" % (filename, xslfile)) + logging.error("Error attempting to parse %s or %s" % (filename, xslfile)) return False if xsl.validate(doc): - logging.debug("%s validates against %s" % (filename, xslfile)) - #print "%s validates against %s" % (filename, xslfile) + logging.info("%s validates against %s" % (filename, xslfile)) + print "%s validates against %s" % (filename, xslfile) return True else: - logging.debug("%s did not validate against %s" % (filename, xslfile)) - #print "%s did not validate against %s" % (filename, xslfile) + logging.info("%s did not validate against %s" % (filename, xslfile)) + print "%s did not validate against %s" % (filename, xslfile) return False Modified: pytrainer/branches/plugins-v2/pytrainer/main.py =================================================================== --- pytrainer/branches/plugins-v2/pytrainer/main.py 2009-10-10 00:16:17 UTC (rev 362) +++ pytrainer/branches/plugins-v2/pytrainer/main.py 2009-10-11 08:22:55 UTC (rev 363) @@ -25,6 +25,7 @@ pygtk.require('2.0') import gtk import gtk.glade +from optparse import OptionParser import logging import logging.handlers import traceback @@ -60,21 +61,26 @@ # 21.03.2008 - dgranda (updated 17.04.2008) # Only one parameter from command line is accepted # ERROR is the default log level -log_level = logging.ERROR PATH = os.environ['HOME']+"/.pytrainer" if not os.path.exists(PATH): os.mkdir(PATH) LOG_FILENAME = PATH + "/log.out" -if len(sys.argv) > 1: - if sys.argv[1]=='-d': - log_level = logging.DEBUG - elif sys.argv[1]=='-i': - log_level = logging.INFO - elif sys.argv[1]=='-w': - log_level = logging.WARNING - else: - print "CLI - Unknown parameter "+sys.argv[1] +#Setup usage and permitted options +usage = """usage: %prog [options] + +For more help on valid options try: + %prog -h """ +parser = OptionParser(usage=usage) +parser.set_defaults(log_level=logging.ERROR, validate=False) +parser.add_option("-d", "--debug", action="store_const", const=logging.DEBUG, dest="log_level", help="enable logging at debug level") +parser.add_option("-i", "--info", action="store_const", const=logging.INFO, dest="log_level", help="enable logging at info level") +parser.add_option("-w", "--warn", action="store_const", const=logging.WARNING, dest="log_level", help="enable logging at warning level") +parser.add_option("--valid", action="store_true", dest="validate", help="enable validation of files imported by plugins (details at info or debug logging level) - note plugin must support validation") +(options, args) = parser.parse_args() +log_level = options.log_level +validate = options.validate + # Adding rotating support to default logger with customized format rotHandler = logging.handlers.RotatingFileHandler(LOG_FILENAME, maxBytes=100000, backupCount=5) formatter = logging.Formatter('%(asctime)s|%(levelname)s|%(module)s|%(funcName)s|%(message)s') @@ -95,6 +101,7 @@ #self.profile.setVersion("0.0") self.profile.isProfileConfigured() self.log_level = log_level + self.validate = validate logging.debug('checking configuration...') self.conf = checkConf() Modified: pytrainer/branches/plugins-v2/pytrainer/plugins.py =================================================================== --- pytrainer/branches/plugins-v2/pytrainer/plugins.py 2009-10-10 00:16:17 UTC (rev 362) +++ pytrainer/branches/plugins-v2/pytrainer/plugins.py 2009-10-11 08:22:55 UTC (rev 363) @@ -60,9 +60,10 @@ module = __import__(plugin_filename) pluginMain = getattr(module, plugin_classname) logging.debug('<<') - #Only validate files if in Debug mode - if self.parent.log_level == logging.DEBUG: + #Only validate files if enabled at startup + if self.parent.validate: validate_inputfiles=True + print "validating plugin input files enabled" else: validate_inputfiles=False return pluginMain(self, validate_inputfiles) Modified: pytrainer/branches/plugins-v2/pytrainer.sh =================================================================== --- pytrainer/branches/plugins-v2/pytrainer.sh 2009-10-10 00:16:17 UTC (rev 362) +++ pytrainer/branches/plugins-v2/pytrainer.sh 2009-10-11 08:22:55 UTC (rev 363) @@ -6,4 +6,4 @@ PATH_XULRUNNER=/usr/lib XULRUNNER_VERSION=`ls "$PATH_XULRUNNER" | grep xulrunner` export MOZILLA_FIVE_HOME=$PATH_XULRUNNER/$XULRUNNER_VERSION -python pytrainer.py $1 +python pytrainer.py $* This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-10-10 00:16:30
|
Revision: 362 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=362&view=rev Author: jblance Date: 2009-10-10 00:16:17 +0000 (Sat, 10 Oct 2009) Log Message: ----------- Support for TCX v2 in plugins branch Modified Paths: -------------- pytrainer/branches/plugins-v2/plugins/garmin-gpx/garmingpx.py pytrainer/branches/plugins-v2/plugins/garmin-hr-file/garminhrfile.py pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/conf.xml pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/garmin-tcxv2.py Modified: pytrainer/branches/plugins-v2/plugins/garmin-gpx/garmingpx.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-gpx/garmingpx.py 2009-09-25 11:45:17 UTC (rev 361) +++ pytrainer/branches/plugins-v2/plugins/garmin-gpx/garmingpx.py 2009-10-10 00:16:17 UTC (rev 362) @@ -34,18 +34,20 @@ self.validate = validate def run(self): + logging.debug(">>") selectedFiles = fileChooserDialog(title="Choose a GPX file (or files) to import", multiple=True).getFiles() guiFlush() - importFiles = [] + importfiles = [] for filename in selectedFiles: if self.valid_input_file(filename): if not self.inDatabase(filename): - importFiles.append(filename) + importfiles.append(filename) else: - logging.debug("%s already in database. Skipping import." % (filename,) ) + logging.debug("%s already in database. Skipping import." % (filename) ) else: logging.debug("Invalid input file %s" % (filename)) - return importFiles + logging.debug("<<") + return importfiles def valid_input_file(self, filename): """ Function to validate input file if requested""" @@ -61,7 +63,10 @@ return validator.validateXSL(filename, topografixXSLfile) and validator.validateXSL(filename, cluetrustXSLfile) def inDatabase(self, filename): - #comparing date and start time (sport may have been changed in DB after import) + """ Function to determine if a given file has already been imported into the database + only compares date and start time (sport may have been changed in DB after import) + only valid for GPX files with a single activity + """ time = self.detailsFromGPX(filename) if self.parent.parent.ddbb.select("records","*","date_time_utc=\"%s\"" % (time)): return True @@ -69,6 +74,7 @@ return False def detailsFromGPX(self, filename): + """ Function to return the first time element from a GPX 1.1 file """ tree = xml.etree.cElementTree.ElementTree(file=filename) root = tree.getroot() timeElement = root.find(".//{http://www.topografix.com/GPX/1/1}time") Modified: pytrainer/branches/plugins-v2/plugins/garmin-hr-file/garminhrfile.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr-file/garminhrfile.py 2009-09-25 11:45:17 UTC (rev 361) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr-file/garminhrfile.py 2009-10-10 00:16:17 UTC (rev 362) @@ -41,6 +41,7 @@ self.validate = validate def run(self): + logging.debug(">>") selectedFiles = fileChooserDialog(title="Choose a Garmin Training Center file to import").getFiles() guiFlush() importfiles = [] @@ -58,6 +59,7 @@ logging.debug("Importing %s of %s tracks" % (len(importfiles), len(tracks)) ) else: logging.debug("Invalid input file %s" % (filename)) + logging.debug("<<") return importfiles def valid_input_file(self, filename): @@ -97,7 +99,7 @@ return tracks def createGPXfile(self, gpxfile, track): - """ Function to transform a Garmin Training Center v1 Track to a valid GPX file + """ Function to transform a Garmin Training Center v1 Track to a valid GPX+ file """ xslt_doc = etree.parse(self.data_path+"/translate.xsl") transform = etree.XSLT(xslt_doc) Modified: pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/conf.xml =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/conf.xml 2009-09-25 11:45:17 UTC (rev 361) +++ pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/conf.xml 2009-10-10 00:16:17 UTC (rev 362) @@ -3,7 +3,7 @@ name="Garmin v2 TCX" description="Import your records from a version 2 TCX file from a Garmin gps device (i.e. Forerunner 405)" plugincode="garminTCXv2" - pluginbutton="Import from Garmin TCX (version 2)" + pluginbutton="Import from Garmin TCX file (version 2)" executable="garmin-tcxv2" > </pytrainer-plugin> Modified: pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/garmin-tcxv2.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/garmin-tcxv2.py 2009-09-25 11:45:17 UTC (rev 361) +++ pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/garmin-tcxv2.py 2009-10-10 00:16:17 UTC (rev 362) @@ -19,39 +19,72 @@ import logging import os -import libxml2 -import libxslt +from lxml import etree +from gui.dialogs import fileChooserDialog, guiFlush + class garminTCXv2(): - def __init__(self, parent = None): + def __init__(self, parent = None, validate=False): self.parent = parent self.tmpdir = self.parent.conf.getValue("tmpdir") + self.data_path = os.path.dirname(__file__) + self.validate = validate def run(self): logging.debug(">>") # able to select multiple files.... - f = os.popen("zenity --file-selection --multiple --title 'Choose a TCX file to import'") - inputData = f.read().strip() - inputfiles = inputData.split('|') - xslfile= os.path.dirname(os.path.realpath(__file__)) + "/translate.xsl" - outputfile=[] - if os.path.isfile(xslfile): - for index in range(len(inputfiles)): - outputfile.append(self.tmpdir+"/outputfile"+str(index)+".gpx") - inputfile=inputfiles[index] - if os.path.isfile(inputfile): - styledoc = libxml2.parseFile(xslfile) - style = libxslt.parseStylesheetDoc(styledoc) - doc = libxml2.parseFile(inputfile) - result = style.applyStylesheet(doc, None) - style.saveResultToFilename(outputfile[index], result, 0) - style.freeStylesheet() - doc.freeDoc() - result.freeDoc() + selectedFiles = fileChooserDialog(title="Choose a TCX file (or files) to import", multiple=True).getFiles() + guiFlush() + importfiles = [] + if not selectedFiles: #Nothing selected + return importfiles + for filename in selectedFiles: + if self.valid_input_file(filename): + if not self.inDatabase(filename): + gpxfile = "%s/garmin-tcxv2-%d.gpx" % (self.tmpdir, len(importfiles)) + self.createGPXfile(gpxfile, filename) + importfiles.append(gpxfile) else: - raise Exception("XML input file not found, looking for: " + inputfile) - else: - raise Exception("XSL file not found, looking for: " + xslfile) + logging.debug("%s already in database. Skipping import." % (filename,) ) + else: + logging.debug("Invalid input file %s" % (filename)) logging.debug("<<") - return outputfile + return importfiles + def valid_input_file(self, filename): + """ Function to validate input file if requested""" + if not self.validate: + #not asked to validate + return True + else: + xslfile = os.path.realpath(self.parent.parent.data_path)+ "/schemas/GarminTrainingCenterDatabase_v2.xsd" + from lib.xmlValidation import xmlValidator + validator = xmlValidator() + return validator.validateXSL(filename, xslfile) + + def inDatabase(self, filename): + #comparing date and start time (sport may have been changed in DB after import) + time = self.detailsFromTCX(filename) + if self.parent.parent.ddbb.select("records","*","date_time_utc=\"%s\"" % (time)): + return True + else: + return False + + def detailsFromTCX(self, filename): + tree = etree.ElementTree(file=filename) + root = tree.getroot() + timeElement = root.find(".//{http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2}Id") + if timeElement is None: + return None + else: + return timeElement.text + + def createGPXfile(self, gpxfile, filename): + """ Function to transform a Garmin Training Center v2 Track to a valid GPX+ file + """ + xslt_doc = etree.parse(self.data_path+"/translate.xsl") + transform = etree.XSLT(xslt_doc) + xml_doc = etree.parse(filename) + result_tree = transform(xml_doc) + result_tree.write(gpxfile) + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-09-25 11:45:31
|
Revision: 361 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=361&view=rev Author: jblance Date: 2009-09-25 11:45:17 +0000 (Fri, 25 Sep 2009) Log Message: ----------- Added XSL validation to plugin branch Modified Paths: -------------- pytrainer/branches/plugins-v2/plugins/garmin-gpx/garmingpx.py pytrainer/branches/plugins-v2/plugins/garmin-hr-file/garminhrfile.py pytrainer/branches/plugins-v2/pytrainer/main.py pytrainer/branches/plugins-v2/pytrainer/plugins.py Added Paths: ----------- pytrainer/branches/plugins-v2/pytrainer/lib/xmlValidation.py pytrainer/branches/plugins-v2/schemas/ pytrainer/branches/plugins-v2/schemas/Cluetrust_gpxdata10.xsd pytrainer/branches/plugins-v2/schemas/GarminTrainingCenterDatabase_v1-gpsbabel.xsd pytrainer/branches/plugins-v2/schemas/GarminTrainingCenterDatabase_v1.xsd pytrainer/branches/plugins-v2/schemas/GarminTrainingCenterDatabase_v2.xsd pytrainer/branches/plugins-v2/schemas/README pytrainer/branches/plugins-v2/schemas/Topografix_gpx11.xsd pytrainer/branches/plugins-v2/schemas/validate_gpsfile.py Modified: pytrainer/branches/plugins-v2/plugins/garmin-gpx/garmingpx.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-gpx/garmingpx.py 2009-09-25 10:22:03 UTC (rev 360) +++ pytrainer/branches/plugins-v2/plugins/garmin-gpx/garmingpx.py 2009-09-25 11:45:17 UTC (rev 361) @@ -19,6 +19,7 @@ #Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. import logging +import os from gui.dialogs import fileChooserDialog, guiFlush import xml.etree.cElementTree @@ -27,22 +28,38 @@ Expects only one activity in each file Checks to see if any entries are in the database with the same start time """ - def __init__(self, parent = None): + def __init__(self, parent = None, validate=False): self.parent = parent self.tmpdir = self.parent.conf.getValue("tmpdir") + self.validate = validate def run(self): selectedFiles = fileChooserDialog(title="Choose a GPX file (or files) to import", multiple=True).getFiles() guiFlush() importFiles = [] for filename in selectedFiles: - if not self.inDatabase(filename): - importFiles.append(filename) + if self.valid_input_file(filename): + if not self.inDatabase(filename): + importFiles.append(filename) + else: + logging.debug("%s already in database. Skipping import." % (filename,) ) else: - print "%s already in database. Skipping import." % (filename,) - logging.debug("%s already in database. Skipping import." % (filename,) ) + logging.debug("Invalid input file %s" % (filename)) return importFiles + def valid_input_file(self, filename): + """ Function to validate input file if requested""" + if not self.validate: + #not asked to validate + return True + else: + #To validate GPX as used for pytrainer must test against both Topograpfix and Cluetrust + topografixXSLfile = os.path.realpath(self.parent.parent.data_path)+ "/schemas/Topografix_gpx11.xsd" + cluetrustXSLfile = os.path.realpath(self.parent.parent.data_path)+ "/schemas/Cluetrust_gpxdata10.xsd" + from lib.xmlValidation import xmlValidator + validator = xmlValidator() + return validator.validateXSL(filename, topografixXSLfile) and validator.validateXSL(filename, cluetrustXSLfile) + def inDatabase(self, filename): #comparing date and start time (sport may have been changed in DB after import) time = self.detailsFromGPX(filename) Modified: pytrainer/branches/plugins-v2/plugins/garmin-hr-file/garminhrfile.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr-file/garminhrfile.py 2009-09-25 10:22:03 UTC (rev 360) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr-file/garminhrfile.py 2009-09-25 11:45:17 UTC (rev 361) @@ -34,10 +34,11 @@ Note: using lxml see http://codespeak.net/lxml """ - def __init__(self, parent = None): + def __init__(self, parent = None, validate=False): self.parent = parent self.tmpdir = self.parent.conf.getValue("tmpdir") self.data_path = os.path.dirname(__file__) + self.validate = validate def run(self): selectedFiles = fileChooserDialog(title="Choose a Garmin Training Center file to import").getFiles() @@ -46,15 +47,29 @@ if not selectedFiles: return importfiles for filename in selectedFiles: #could be multiple files selected - currently only single selection enabled - tracks = self.getTracks(filename) - logging.debug("Found %d tracks in %s" % (len(tracks), filename)) - for track in tracks: #can be multiple tracks - if shouldImport(track): - gpxfile = "%s/garminhrfile%d.gpx" % (self.tmpdir, len(importfiles)) - self.createGPXfile(gpxfile, track) - importfiles.append(gpxfile) + if self.valid_input_file(filename): + tracks = self.getTracks(filename) + logging.debug("Found %d tracks in %s" % (len(tracks), filename)) + for track in tracks: #can be multiple tracks + if self.shouldImport(track): + gpxfile = "%s/garminhrfile%d.gpx" % (self.tmpdir, len(importfiles)) + self.createGPXfile(gpxfile, track) + importfiles.append(gpxfile) + logging.debug("Importing %s of %s tracks" % (len(importfiles), len(tracks)) ) + else: + logging.debug("Invalid input file %s" % (filename)) return importfiles + def valid_input_file(self, filename): + """ Function to validate input file if requested""" + if not self.validate: #not asked to validate + return True + else: #Validate TCXv1, note are validating against gpsbabels 'broken' result... + xslfile = os.path.realpath(self.parent.parent.data_path)+ "/schemas/GarminTrainingCenterDatabase_v1-gpsbabel.xsd" + from lib.xmlValidation import xmlValidator + validator = xmlValidator() + return validator.validateXSL(filename, xslfile) + def shouldImport(self, track): """ Function determines whether a track should be imported or not Currently using time only @@ -68,9 +83,10 @@ time = timeElement.text #comparing date and start time (sport may have been changed in DB after import) if self.parent.parent.ddbb.select("records","*","date_time_utc=\"%s\"" % (time)): + logging.debug("Not importing track for time %s" % (time)) + return False + else: return True - else: - return False def getTracks(self, filename): """ Function to return all the tracks in a Garmin Training Center v1 file Added: pytrainer/branches/plugins-v2/pytrainer/lib/xmlValidation.py =================================================================== --- pytrainer/branches/plugins-v2/pytrainer/lib/xmlValidation.py (rev 0) +++ pytrainer/branches/plugins-v2/pytrainer/lib/xmlValidation.py 2009-09-25 11:45:17 UTC (rev 361) @@ -0,0 +1,38 @@ +# -*- coding: iso-8859-1 -*- + +#Copyright (C) + +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either version 2 +#of the License, or (at your option) any later version. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. + +#You should have received a copy of the GNU General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import logging +from lxml import etree + +class xmlValidator(): + def validateXSL(self, filename, xslfile): + try: + doc = etree.parse(filename) + xsl_doc = etree.parse(xslfile) + xsl = etree.XMLSchema(xsl_doc) + except: + logging.debug("Error attempting to parse %s or %s" % (filename, xslfile)) + return False + if xsl.validate(doc): + logging.debug("%s validates against %s" % (filename, xslfile)) + #print "%s validates against %s" % (filename, xslfile) + return True + else: + logging.debug("%s did not validate against %s" % (filename, xslfile)) + #print "%s did not validate against %s" % (filename, xslfile) + return False Modified: pytrainer/branches/plugins-v2/pytrainer/main.py =================================================================== --- pytrainer/branches/plugins-v2/pytrainer/main.py 2009-09-25 10:22:03 UTC (rev 360) +++ pytrainer/branches/plugins-v2/pytrainer/main.py 2009-09-25 11:45:17 UTC (rev 361) @@ -94,6 +94,7 @@ self.profile = Profile(self.data_path,self) #self.profile.setVersion("0.0") self.profile.isProfileConfigured() + self.log_level = log_level logging.debug('checking configuration...') self.conf = checkConf() Modified: pytrainer/branches/plugins-v2/pytrainer/plugins.py =================================================================== --- pytrainer/branches/plugins-v2/pytrainer/plugins.py 2009-09-25 10:22:03 UTC (rev 360) +++ pytrainer/branches/plugins-v2/pytrainer/plugins.py 2009-09-25 11:45:17 UTC (rev 361) @@ -60,7 +60,12 @@ module = __import__(plugin_filename) pluginMain = getattr(module, plugin_classname) logging.debug('<<') - return pluginMain(self) + #Only validate files if in Debug mode + if self.parent.log_level == logging.DEBUG: + validate_inputfiles=True + else: + validate_inputfiles=False + return pluginMain(self, validate_inputfiles) Added: pytrainer/branches/plugins-v2/schemas/Cluetrust_gpxdata10.xsd =================================================================== --- pytrainer/branches/plugins-v2/schemas/Cluetrust_gpxdata10.xsd (rev 0) +++ pytrainer/branches/plugins-v2/schemas/Cluetrust_gpxdata10.xsd 2009-09-25 11:45:17 UTC (rev 361) @@ -0,0 +1,234 @@ +<?xml version = "1.0" encoding = "UTF-8"?> +<!--Generated by Turbo XML 2.4.1.100. Conforms to w3c http://www.w3.org/2001/XMLSchema--> +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns="http://www.cluetrust.com/XML/GPXDATA/1/0" xmlns:gpx="http://www.topografix.com/GPX/1/1" + targetNamespace="http://www.cluetrust.com/XML/GPXDATA/1/0" elementFormDefault="qualified"> + <xsd:annotation> + <xsd:documentation> + The GPXData schema is an mix-in schema for use with the GPX 1.1 schema from Topografix. It was designed with the intent of + expanding GPX (using the existing mechanisms) to contain additional content from GPS receivers commonly used for sporting and + geocaching activities. + </xsd:documentation> + </xsd:annotation> + <xsd:import namespace="http://www.topografix.com/GPX/1/1" + schemaLocation="http://www.topografix.com/GPX/1/1/gpx.xsd"/> + + <xsd:element name="hr" type="xsd:nonNegativeInteger"> + <xsd:annotation> + <xsd:documentation> + HR represents the heart rate in beats per minute. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="cadence" type="xsd:nonNegativeInteger"> + <xsd:annotation> + <xsd:documentation> + Cadence represents the cadence in revolutions per minute. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="temp" type="xsd:decimal"> + <xsd:annotation> + <xsd:documentation> + Temp represents the temperature in degrees celcius + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="distance" type="distanceType"> + <xsd:annotation><xsd:documentation>Distance in meters as measured by GPS or wheel sensor</xsd:documentation></xsd:annotation> + </xsd:element> + <xsd:element name="sensor" type="sensorType"> + <xsd:annotation><xsd:documentation>Set if there is a sensor present</xsd:documentation></xsd:annotation> + </xsd:element> + <xsd:element name="run" type="runType"> + <xsd:annotation><xsd:documentation>On devices that have the concept of a run, the run encapsulates laps and provides overall summary information</xsd:documentation></xsd:annotation> + </xsd:element> + <xsd:element name="dataPt" type="dataPointType"> + <xsd:annotation><xsd:documentation>Added if there is data available that doesn't have position information</xsd:documentation></xsd:annotation> + </xsd:element> + <xsd:element name="lap" type="lapType"> + <xsd:annotation> + <xsd:documentation> + Lap is used to contain information about an individual lap of activity. + Depending upon the device, this may contain a variety of additional information. + Depending upon the device, this may be contained within a run or course. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="course" type="courseType"> + <xsd:annotation> + <xsd:documentation> + Course is used to contain additional information about a course downloaded to the GPS as a track. + Depending on the device, this may be uploaded as part of the data or left empty. + Always appears in a track. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:complexType name="dataPointType"> + <xsd:annotation> + <xsd:documentation> + dataPt is used to store information about non-geographic data point. This is useful when HR or other + data is present, but no latitude or longitude data is. + </xsd:documentation> + </xsd:annotation> + <xsd:sequence> + <xsd:element name="time" type="xsd:dateTime"/> + <xsd:element name="ele" type="xsd:decimal" minOccurs="0" maxOccurs="1"/> + <xsd:element ref="hr" minOccurs="0" maxOccurs="1"/> + <xsd:element ref="cadence" minOccurs="0" maxOccurs="1"/> + <xsd:element ref="temp" minOccurs="0" maxOccurs="1"/> + <xsd:element ref="distance" minOccurs="0" maxOccurs="1"/> + <xsd:element ref="sensor" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="runType"> + <xsd:sequence> + <xsd:element name="sport" type="sportType" minOccurs="0" maxOccurs="1"> + <xsd:annotation><xsd:documentation>The type of sport being participated in</xsd:documentation></xsd:annotation> + </xsd:element> + <xsd:element name="programType" type="xsd:anySimpleType" minOccurs="0" maxOccurs="1"> + <xsd:annotation><xsd:documentation>The type of program being executed</xsd:documentation></xsd:annotation> + </xsd:element> + <xsd:element name="laps" minOccurs="0" maxOccurs="1"> + <xsd:annotation><xsd:documentation>Group of laps that make up the run</xsd:documentation></xsd:annotation> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="lap" type="lapType" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="courseType"> + <xsd:sequence> + <xsd:element name="index" type="xsd:int" minOccurs="0" maxOccurs="1"> + <xsd:annotation><xsd:documentation>Index of the course in the GPS.</xsd:documentation></xsd:annotation> + </xsd:element> + <xsd:element name="laps" minOccurs="0" maxOccurs="1"> + <xsd:annotation><xsd:documentation>Group of laps that make up the course</xsd:documentation></xsd:annotation> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="lap" type="lapType" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="lapType"> + <xsd:sequence> + <xsd:element name="index" type="xsd:int" minOccurs="0" maxOccurs="1"> + <xsd:annotation><xsd:documentation>The index of the lap in the internal list.</xsd:documentation></xsd:annotation> + </xsd:element> + <xsd:element name="startPoint" type="locationType" minOccurs="0" maxOccurs="1"> + <xsd:annotation><xsd:documentation>The starting point of the lap in Lat/Long</xsd:documentation></xsd:annotation> + </xsd:element> + <xsd:element name="endPoint" type="locationType" minOccurs="0" maxOccurs="1"> + <xsd:annotation><xsd:documentation>The ending point of the lap in Lat/Long</xsd:documentation></xsd:annotation> + </xsd:element> + <xsd:element name="startTime" type="xsd:dateTime" minOccurs="0" maxOccurs="1"> + <xsd:annotation><xsd:documentation>The starting time of the lap</xsd:documentation></xsd:annotation> + </xsd:element> + <xsd:element name="elapsedTime" type="xsd:float" minOccurs="0" maxOccurs="1"> + <xsd:annotation><xsd:documentation>The total elapsed time of the lap in seconds</xsd:documentation></xsd:annotation> + </xsd:element> + <xsd:element name="calories" type="xsd:nonNegativeInteger" minOccurs="0" maxOccurs="1"> + <xsd:annotation><xsd:documentation>The number of calories burned during the lap</xsd:documentation></xsd:annotation> + </xsd:element> + <xsd:element name="distance" type="xsd:float" minOccurs="0" maxOccurs="1"> + <xsd:annotation><xsd:documentation>Distance (in m) covered during the lap</xsd:documentation></xsd:annotation> + </xsd:element> + <xsd:element name="trackReference" type="trackReferenceType" minOccurs="0" maxOccurs="1"> + <xsd:annotation><xsd:documentation>Reference information for the track which corresponds to this lap</xsd:documentation></xsd:annotation> + </xsd:element> + <xsd:element name="summary" type="summaryType" minOccurs="0" maxOccurs="unbounded"> + <xsd:annotation><xsd:documentation>Performance summary elements summarizing different performance measurements, such as cadence, hr, etc.</xsd:documentation></xsd:annotation> + </xsd:element> + <xsd:element name="trigger" type="triggerType" minOccurs="0" maxOccurs="1"> + <xsd:annotation><xsd:documentation>The trigger of the lap. On some devices, the lap may be manual or automatic based on attributes known by the device.</xsd:documentation></xsd:annotation> + </xsd:element> + <xsd:element name="intensity" type="intensityKind" minOccurs="0" maxOccurs="1"> + <xsd:annotation><xsd:documentation>The intensity of the lap (whether resting or active)</xsd:documentation></xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="sportType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="bike"/> + <xsd:enumeration value="run"/> + <xsd:enumeration value="other"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="distanceType"> + <xsd:simpleContent> + <xsd:extension base="xsd:decimal"> + <xsd:attribute name="sensor" use="optional" type="sensorKind"></xsd:attribute> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + <xsd:complexType name="sensorType"> + <xsd:attribute name="kind" use="required" type="sensorKind"/> + </xsd:complexType> + <xsd:simpleType name="sensorKind"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="wheel"/> + <xsd:enumeration value="pedometer"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="summaryType"> + <xsd:simpleContent> + <xsd:extension base="xsd:decimal"> + <xsd:attribute name="name" use="required" type="xsd:string"/> + <xsd:attribute name="kind" use="required" type="summaryKind"/> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + <xsd:simpleType name="summaryKind"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="max"/> + <xsd:enumeration value="min"/> + <xsd:enumeration value="avg"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="triggerType"> + <xsd:simpleContent> + <xsd:extension base="xsd:anySimpleType"> + <xsd:attribute name="kind" use="required" type="triggerKind"/> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + <xsd:simpleType name="triggerKind"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="manual"/> + <xsd:enumeration value="time"/> + <xsd:enumeration value="distance"/> + <xsd:enumeration value="location"/> + <xsd:enumeration value="hr"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="intensityKind"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="rest"/> + <xsd:enumeration value="active"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="locationType"> + <xsd:attribute name="lat" use="required" type="gpx:latitudeType"/> + <xsd:attribute name="lon" use="required" type="gpx:longitudeType"/> + </xsd:complexType> + <xsd:complexType name="trackReferenceType"> + <xsd:sequence> + <xsd:element name="startPoint" type="xsd:nonNegativeInteger" minOccurs="0"> + <xsd:annotation><xsd:documentation>Index into the referenced track of the point that this lap starts on</xsd:documentation></xsd:annotation> + </xsd:element> + <xsd:element name="endPoint" type="xsd:nonNegativeInteger" minOccurs="0"> + <xsd:annotation><xsd:documentation>Index into the referenced track of the point that this lap starts on</xsd:documentation></xsd:annotation> + </xsd:element> + </xsd:sequence> + <xsd:attribute name="trackNumber" type="xsd:nonNegativeInteger" use="optional"> + <xsd:annotation><xsd:documentation>Reference by number to the track (matches number)</xsd:documentation></xsd:annotation> + </xsd:attribute> + <xsd:attribute name="trackName" type="xsd:string" use="optional"> + <xsd:annotation><xsd:documentation>Reference by name to the track (matches name)</xsd:documentation></xsd:annotation> + </xsd:attribute> + </xsd:complexType> +</xsd:schema> Added: pytrainer/branches/plugins-v2/schemas/GarminTrainingCenterDatabase_v1-gpsbabel.xsd =================================================================== --- pytrainer/branches/plugins-v2/schemas/GarminTrainingCenterDatabase_v1-gpsbabel.xsd (rev 0) +++ pytrainer/branches/plugins-v2/schemas/GarminTrainingCenterDatabase_v1-gpsbabel.xsd 2009-09-25 11:45:17 UTC (rev 361) @@ -0,0 +1,656 @@ +<?xml version="1.0"?> +<xsd:schema xmlns="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" + targetNamespace="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v1" xmlns:tc1="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v1" + elementFormDefault="qualified"> + <xsd:annotation> + <xsd:documentation> + This schema defines the Garmin Training Center file format. + </xsd:documentation> + </xsd:annotation> + <xsd:element name="TrainingCenterDatabase" type="TrainingCenterDatabase_t"/> + <xsd:complexType name="TrainingCenterDatabase_t"> + <xsd:sequence> + <xsd:element name="History" type="History_t" minOccurs="0"/> + <xsd:element name="Workouts" type="Workouts_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation> + The workouts stored in a workout file should have unique names. + </xsd:documentation> + </xsd:annotation> + <xsd:unique name="WorkoutNameMustBeUnique"> + <xsd:selector xpath="tc1:Workout"/> + <xsd:field xpath="tc1:Name"/> + </xsd:unique> + </xsd:element> + <xsd:element name="Courses" type="Courses_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation> + The courses stored in a course file should have unique names. + </xsd:documentation> + </xsd:annotation> + <xsd:unique name="CourseNameMustBeUnique"> + <xsd:selector xpath="tc1:Course"/> + <xsd:field xpath="tc1:Name"/> + </xsd:unique> + </xsd:element> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="History_t"> + <xsd:sequence> + <xsd:element name="Running" type="HistoryFolder_t"/> + <xsd:element name="Biking" type="HistoryFolder_t"/> + <xsd:element name="Other" type="HistoryFolder_t"/> + <xsd:element name="MultiSport" type="MultiSportFolder_t"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="HistoryFolder_t"> + <xsd:sequence> + <xsd:element name="Folder" type="HistoryFolder_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Run" type="Run_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Week" type="Week_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Notes" type="xsd:string" minOccurs="0"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + <xsd:attribute name="Name" type="xsd:string" /> + </xsd:complexType> + <xsd:complexType name="MultiSportFolder_t"> + <xsd:sequence> + <xsd:element name="Folder" type="MultiSportFolder_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="MultiSportSession" type="MultiSportSession_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Week" type="Week_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Notes" type="xsd:string" minOccurs="0"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + <xsd:attribute name="Name" type="xsd:string"/> + </xsd:complexType> + <xsd:complexType name="Week_t"> + <xsd:sequence> + <xsd:annotation> + <xsd:documentation> + The week is written out only if the notes are present. + </xsd:documentation> + </xsd:annotation> + <xsd:element name="Notes" type="xsd:string" minOccurs="0"/> + </xsd:sequence> + <xsd:attribute name="StartDay" type="xsd:date" use="required"/> + </xsd:complexType> + <xsd:complexType name="MultiSportSession_t"> + <xsd:sequence> + <xsd:element name="FirstSport" type="FirstSport_t"/> + <xsd:element name="NextSport" type="NextSport_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Notes" type="xsd:string" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="FirstSport_t"> + <xsd:sequence> + <xsd:element name="Run" type="Run_t"/> + </xsd:sequence> + <xsd:attribute name="Sport" type="Sport_t" use="required"/> + </xsd:complexType> + <xsd:complexType name="NextSport_t"> + <xsd:sequence> + <xsd:annotation> + <xsd:documentation> + Each sport contains an optional transition and a run. + </xsd:documentation> + </xsd:annotation> + <xsd:element name="Transition" type="ActivityLap_t" minOccurs="0"/> + <xsd:element name="Run" type="Run_t"/> + </xsd:sequence> + <xsd:attribute name="Sport" type="Sport_t" use="required"/> + </xsd:complexType> + <xsd:simpleType name="Sport_t"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="Running"/> + <xsd:enumeration value="Biking"/> + <xsd:enumeration value="Other"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="Run_t"> + <xsd:sequence> + <xsd:element name="Lap" type="ActivityLap_t" maxOccurs="unbounded"/> + <xsd:element name="Notes" type="xsd:string" minOccurs="0"/> + <xsd:element name="Training" type="Training_t" minOccurs="0"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="Training_t"> + <xsd:sequence> + <xsd:element name="QuickWorkoutResults" type="QuickWorkout_t" minOccurs="0"/> + <xsd:element name="Plan" type="Plan_t" minOccurs="0"/> + </xsd:sequence> + <xsd:attribute name="VirtualPartner" type="xsd:boolean" use="required"/> + </xsd:complexType> + <xsd:complexType name="QuickWorkout_t"> + <xsd:sequence> + <xsd:element name="TotalTimeSeconds" type="xsd:double"/> + <xsd:element name="DistanceMeters" type="xsd:double"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="Plan_t"> + <xsd:sequence> + <xsd:element name="Name" type="RestrictedToken_t" minOccurs="0"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + <xsd:attribute name="Type" type="TrainingType_t" use="required"/> + <xsd:attribute name="IntervalWorkout" type="xsd:boolean" use="required"/> + </xsd:complexType> + <xsd:simpleType name="TrainingType_t"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="Workout"/> + <xsd:enumeration value="Course"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="ActivityLap_t"> + <xsd:sequence> + <xsd:element name="TotalTimeSeconds" type="xsd:double"/> + <xsd:element name="DistanceMeters" type="xsd:double"/> + <xsd:element name="MaximumSpeed" type="xsd:double" minOccurs="0"/> + <xsd:element name="Calories" type="xsd:unsignedShort"/> + <xsd:element name="AverageHeartRateBpm" type="xsd:unsignedByte" minOccurs="0"/> + <xsd:element name="MaximumHeartRateBpm" type="xsd:unsignedByte" minOccurs="0"/> + <xsd:element name="Intensity" type="Intensity_t"/> + <xsd:element name="Cadence" type="xsd:unsignedByte" minOccurs="0"/> + <xsd:element name="TriggerMethod" type="TriggerMethod_t"/> + <xsd:element name="Track" type="Track_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Notes" type="xsd:string" minOccurs="0"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + <xsd:attribute name="StartTime" type="xsd:dateTime" use="required"/> + </xsd:complexType> + <xsd:simpleType name="TriggerMethod_t"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="Manual"/> + <xsd:enumeration value="Distance"/> + <xsd:enumeration value="Location"/> + <xsd:enumeration value="Time"/> + <xsd:enumeration value="HeartRate"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="Track_t"> + <xsd:sequence> + <xsd:element name="Trackpoint" type="Trackpoint_t" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="Trackpoint_t"> + <xsd:sequence> + <xsd:element name="Time" type="xsd:dateTime"/> + <xsd:element name="Position" type="Position_t" minOccurs="0"/> + <xsd:element name="AltitudeMeters" type="xsd:double" minOccurs="0"/> + <xsd:element name="DistanceMeters" type="xsd:double" minOccurs="0"/> + <xsd:element name="HeartRateBpm" type="xsd:unsignedByte" minOccurs="0"/> + <xsd:element name="Cadence" type="xsd:unsignedByte" minOccurs="0"/> + <xsd:element name="SensorState" type="SensorState_t" minOccurs="0"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="Position_t"> + <xsd:sequence> + <xsd:element name="LatitudeDegrees" type="DegreesLatitude_t"/> + <xsd:element name="LongitudeDegrees" type="DegreesLongitude_t"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="DegreesLongitude_t"> + <xsd:annotation> + <xsd:documentation/> + </xsd:annotation> + <xsd:restriction base="xsd:double"> + <xsd:maxExclusive value="180.0"/> + <xsd:minInclusive value="-180.0"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="DegreesLatitude_t"> + <xsd:annotation> + <xsd:documentation/> + </xsd:annotation> + <xsd:restriction base="xsd:double"> + <xsd:maxInclusive value="90.0"/> + <xsd:minInclusive value="-90.0"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="SensorState_t"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="Present"/> + <xsd:enumeration value="Absent"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="Workouts_t"> + <xsd:sequence> + <xsd:element name="Running" type="WorkoutFolder_t"> + <xsd:unique name="RunningSubFolderNamesMustBeUnique"> + <xsd:selector xpath="tc1:Folder"/> + <xsd:field xpath="@Name"/> + </xsd:unique> + </xsd:element> + <xsd:element name="Biking" type="WorkoutFolder_t"> + <xsd:unique name="BikingSubFolderNamesMustBeUnique"> + <xsd:selector xpath="tc1:Folder"/> + <xsd:field xpath="@Name"/> + </xsd:unique> + </xsd:element> + <xsd:element name="Other" type="WorkoutFolder_t"> + <xsd:unique name="OtherSubFolderNamesMustBeUnique"> + <xsd:selector xpath="tc1:Folder"/> + <xsd:field xpath="@Name"/> + </xsd:unique> + </xsd:element> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="WorkoutFolder_t"> + <xsd:sequence> + <xsd:element name="Folder" type="WorkoutFolder_t" minOccurs="0" maxOccurs="unbounded"> + <xsd:unique name="SubFolderNamesMustBeUnique"> + <xsd:selector xpath="tc1:Folder"/> + <xsd:field xpath="@Name"/> + </xsd:unique> + </xsd:element> + <xsd:element name="Workout" type="Workout_t" minOccurs="0" maxOccurs="unbounded"> + <xsd:annotation> + <xsd:documentation> + The StepId should be unique within a workout and should not + exceed 20. This restricts the number of steps in a workout to 20. + </xsd:documentation> + </xsd:annotation> + <xsd:unique name="StepIdMustBeUnique"> + <xsd:selector xpath=".//*"/> + <xsd:field xpath="tc1:StepId"/> + </xsd:unique> + </xsd:element> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + <xsd:attribute name="Name" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="Workout_t"> + <xsd:sequence> + <xsd:element name="Name" type="RestrictedToken_t"/> + <xsd:element name="Step" type="AbstractStep_t" maxOccurs="unbounded"/> + <xsd:element name="ScheduledOn" type="xsd:date" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Notes" type="xsd:string" minOccurs="0"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="RestrictedToken_t"> + <xsd:restriction base="xsd:token"> + <xsd:minLength value="1"/> + <xsd:maxLength value="15"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="AbstractStep_t" abstract="true"> + <xsd:sequence> + <xsd:element name="StepId" type="StepId_t"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="StepId_t"> + <xsd:restriction base="xsd:positiveInteger"> + <xsd:maxInclusive value="20"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="Repeat_t"> + <xsd:complexContent> + <xsd:extension base="AbstractStep_t"> + <xsd:sequence> + <xsd:element name="Repetitions" type="Repetitions_t"/> + <xsd:element name="Child" type="AbstractStep_t" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:simpleType name="Repetitions_t"> + <xsd:restriction base="xsd:positiveInteger"> + <xsd:minInclusive value="2"/> + <xsd:maxInclusive value="99"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="Step_t"> + <xsd:complexContent> + <xsd:extension base="AbstractStep_t"> + <xsd:sequence> + <xsd:element name="Name" type="RestrictedToken_t" minOccurs="0"/> + <xsd:element name="Duration" type="Duration_t"/> + <xsd:element name="Intensity" type="Intensity_t"/> + <xsd:element name="Target" type="Target_t"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="Duration_t" abstract="true"/> + <xsd:simpleType name="Intensity_t"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="Active"/> + <xsd:enumeration value="Resting"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="Target_t" abstract="true"/> + <xsd:complexType name="Time_t"> + <xsd:complexContent> + <xsd:extension base="Duration_t"> + <xsd:sequence> + <xsd:element name="Seconds" type="xsd:unsignedShort"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="Distance_t"> + <xsd:complexContent> + <xsd:extension base="Duration_t"> + <xsd:sequence> + <xsd:element name="Meters" type="xsd:unsignedShort"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="HeartRateAbove_t"> + <xsd:complexContent> + <xsd:extension base="Duration_t"> + <xsd:sequence> + <xsd:element name="HeartRate" type="HeartRateValue_t"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="HeartRateValue_t" abstract="true"/> + <xsd:complexType name="HeartRateBelow_t"> + <xsd:complexContent> + <xsd:extension base="Duration_t"> + <xsd:sequence> + <xsd:element name="HeartRate" type="HeartRateValue_t"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CaloriesBurned_t"> + <xsd:complexContent> + <xsd:extension base="Duration_t"> + <xsd:sequence> + <xsd:element name="Calories" type="xsd:unsignedShort"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="UserInitiated_t"> + <xsd:complexContent> + <xsd:extension base="Duration_t"/> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="Speed_t"> + <xsd:complexContent> + <xsd:extension base="Target_t"> + <xsd:sequence> + <xsd:element name="SpeedZone" type="Zone_t"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="HeartRate_t"> + <xsd:complexContent> + <xsd:extension base="Target_t"> + <xsd:sequence> + <xsd:element name="HeartRateZone" type="Zone_t"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="Cadence_t"> + <xsd:complexContent> + <xsd:extension base="Target_t"> + <xsd:sequence> + <xsd:element name="Low" type="xsd:double"/> + <xsd:element name="High" type="xsd:double"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="None_t"> + <xsd:complexContent> + <xsd:extension base="Target_t"/> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="Zone_t" abstract="true"/> + <xsd:complexType name="PredefinedSpeedZone_t"> + <xsd:complexContent> + <xsd:extension base="Zone_t"> + <xsd:sequence> + <xsd:element name="Number" type="SpeedZoneNumbers_t"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:simpleType name="SpeedZoneNumbers_t"> + <xsd:restriction base="xsd:positiveInteger"> + <xsd:maxInclusive value="10"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CustomSpeedZone_t"> + <xsd:complexContent> + <xsd:extension base="Zone_t"> + <xsd:sequence> + <xsd:element name="ViewAs" type="SpeedType_t"/> + <xsd:element name="LowInMetersPerSecond" type="SpeedInMetersPerSecond_t"/> + <xsd:element name="HighInMetersPerSecond" type="SpeedInMetersPerSecond_t"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:simpleType name="SpeedInMetersPerSecond_t"> + <xsd:restriction base="xsd:double"> + <xsd:minExclusive value="0"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="SpeedType_t"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="Pace"/> + <xsd:enumeration value="Speed"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="PredefinedHeartRateZone_t"> + <xsd:complexContent> + <xsd:extension base="Zone_t"> + <xsd:sequence> + <xsd:element name="Number" type="HeartRateZoneNumbers_t"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:simpleType name="HeartRateZoneNumbers_t"> + <xsd:restriction base="xsd:positiveInteger"> + <xsd:maxInclusive value="5"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CustomHeartRateZone_t"> + <xsd:complexContent> + <xsd:extension base="Zone_t"> + <xsd:sequence> + <xsd:element name="Low" type="HeartRateValue_t"/> + <xsd:element name="High" type="HeartRateValue_t"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="HeartRateInBeatsPerMinute_t"> + <xsd:complexContent> + <xsd:extension base="HeartRateValue_t"> + <xsd:sequence> + <xsd:element name="Value" type="xsd:unsignedByte"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="HeartRateAsPercentOfMax_t"> + <xsd:complexContent> + <xsd:extension base="HeartRateValue_t"> + <xsd:sequence> + <xsd:element name="Value" type="PercentOfMax_t"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:simpleType name="PercentOfMax_t"> + <xsd:restriction base="xsd:unsignedByte"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="100"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="Courses_t"> + <xsd:sequence> + <xsd:element name="CourseFolder" type="CourseFolder_t"> + <xsd:unique name="CourseSubFolderNamesMustBeUnique"> + <xsd:selector xpath="tc1:CourseFolder"/> + <xsd:field xpath="@Name"/> + </xsd:unique> + </xsd:element> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CourseFolder_t"> + <xsd:sequence> + <xsd:element name="Folder" type="CourseFolder_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Course" type="Course_t" minOccurs="0" maxOccurs="unbounded"> + <xsd:unique name="CourseNamesMustBeUnique"> + <xsd:selector xpath="tc1:Course"/> + <xsd:field xpath="tc1:Name"/> + </xsd:unique> + </xsd:element> + <xsd:element name="Notes" type="xsd:string" minOccurs="0"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + <xsd:attribute name="Name" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="Course_t"> + <xsd:sequence> + <xsd:element name="Name" type="RestrictedToken_t"/> + <xsd:element name="Lap" type="CourseLap_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Track" type="Track_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Notes" type="xsd:string" minOccurs="0"/> + <xsd:element name="CoursePoint" type="CoursePoint_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CourseLap_t"> + <xsd:sequence> + <xsd:element name="TotalTimeSeconds" type="xsd:double"/> + <xsd:element name="DistanceMeters" type="xsd:double"/> + <xsd:element name="BeginPosition" type="Position_t" minOccurs="0"/> + <xsd:element name="BeginAltitudeMeters" type="xsd:double" minOccurs="0"/> + <xsd:element name="EndPosition" type="Position_t" minOccurs="0"/> + <xsd:element name="EndAltitudeMeters" type="xsd:double" minOccurs="0"/> + <xsd:element name="AverageHeartRateBpm" type="xsd:unsignedByte" minOccurs="0"/> + <xsd:element name="MaximumHeartRateBpm" type="xsd:unsignedByte" minOccurs="0"/> + <xsd:element name="Intensity" type="Intensity_t"/> + <xsd:element name="Cadence" type="xsd:unsignedByte" minOccurs="0"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CoursePoint_t"> + <xsd:sequence> + <xsd:element name="Name" type="CoursePointName_t"/> + <xsd:element name="Time" type="xsd:dateTime"/> + <xsd:element name="Position" type="Position_t"/> + <xsd:element name="AltitudeMeters" type="xsd:double" minOccurs="0"/> + <xsd:element name="PointType" type="CoursePointType_t"/> + <xsd:element name="Notes" type="xsd:string" minOccurs="0"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="CoursePointName_t"> + <xsd:restriction base="xsd:token"> + <xsd:minLength value="1"/> + <xsd:maxLength value="10"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="CoursePointType_t"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="Generic"/> + <xsd:enumeration value="Summit"/> + <xsd:enumeration value="Valley"/> + <xsd:enumeration value="Water"/> + <xsd:enumeration value="Food"/> + <xsd:enumeration value="Danger"/> + <xsd:enumeration value="Left"/> + <xsd:enumeration value="Right"/> + <xsd:enumeration value="Straight"/> + <xsd:enumeration value="First Aid"/> + <xsd:enumeration value="4th Category"/> + <xsd:enumeration value="3rd Category"/> + <xsd:enumeration value="2nd Category"/> + <xsd:enumeration value="1st Category"/> + <xsd:enumeration value="Hors Category"/> + <xsd:enumeration value="Sprint"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="Extensions_t"> + <xsd:sequence> + <xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:any> + </xsd:sequence> + </xsd:complexType> +</xsd:schema> Added: pytrainer/branches/plugins-v2/schemas/GarminTrainingCenterDatabase_v1.xsd =================================================================== --- pytrainer/branches/plugins-v2/schemas/GarminTrainingCenterDatabase_v1.xsd (rev 0) +++ pytrainer/branches/plugins-v2/schemas/GarminTrainingCenterDatabase_v1.xsd 2009-09-25 11:45:17 UTC (rev 361) @@ -0,0 +1,656 @@ +<?xml version="1.0"?> +<xsd:schema xmlns="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" + targetNamespace="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v1" xmlns:tc1="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v1" + elementFormDefault="qualified"> + <xsd:annotation> + <xsd:documentation> + This schema defines the Garmin Training Center file format. + </xsd:documentation> + </xsd:annotation> + <xsd:element name="TrainingCenterDatabase" type="TrainingCenterDatabase_t"/> + <xsd:complexType name="TrainingCenterDatabase_t"> + <xsd:sequence> + <xsd:element name="History" type="History_t" minOccurs="0"/> + <xsd:element name="Workouts" type="Workouts_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation> + The workouts stored in a workout file should have unique names. + </xsd:documentation> + </xsd:annotation> + <xsd:unique name="WorkoutNameMustBeUnique"> + <xsd:selector xpath="tc1:Workout"/> + <xsd:field xpath="tc1:Name"/> + </xsd:unique> + </xsd:element> + <xsd:element name="Courses" type="Courses_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation> + The courses stored in a course file should have unique names. + </xsd:documentation> + </xsd:annotation> + <xsd:unique name="CourseNameMustBeUnique"> + <xsd:selector xpath="tc1:Course"/> + <xsd:field xpath="tc1:Name"/> + </xsd:unique> + </xsd:element> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="History_t"> + <xsd:sequence> + <xsd:element name="Running" type="HistoryFolder_t"/> + <xsd:element name="Biking" type="HistoryFolder_t"/> + <xsd:element name="Other" type="HistoryFolder_t"/> + <xsd:element name="MultiSport" type="MultiSportFolder_t"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="HistoryFolder_t"> + <xsd:sequence> + <xsd:element name="Folder" type="HistoryFolder_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Run" type="Run_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Week" type="Week_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Notes" type="xsd:string" minOccurs="0"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + <xsd:attribute name="Name" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="MultiSportFolder_t"> + <xsd:sequence> + <xsd:element name="Folder" type="MultiSportFolder_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="MultiSportSession" type="MultiSportSession_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Week" type="Week_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Notes" type="xsd:string" minOccurs="0"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + <xsd:attribute name="Name" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="Week_t"> + <xsd:sequence> + <xsd:annotation> + <xsd:documentation> + The week is written out only if the notes are present. + </xsd:documentation> + </xsd:annotation> + <xsd:element name="Notes" type="xsd:string" minOccurs="0"/> + </xsd:sequence> + <xsd:attribute name="StartDay" type="xsd:date" use="required"/> + </xsd:complexType> + <xsd:complexType name="MultiSportSession_t"> + <xsd:sequence> + <xsd:element name="FirstSport" type="FirstSport_t"/> + <xsd:element name="NextSport" type="NextSport_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Notes" type="xsd:string" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="FirstSport_t"> + <xsd:sequence> + <xsd:element name="Run" type="Run_t"/> + </xsd:sequence> + <xsd:attribute name="Sport" type="Sport_t" use="required"/> + </xsd:complexType> + <xsd:complexType name="NextSport_t"> + <xsd:sequence> + <xsd:annotation> + <xsd:documentation> + Each sport contains an optional transition and a run. + </xsd:documentation> + </xsd:annotation> + <xsd:element name="Transition" type="ActivityLap_t" minOccurs="0"/> + <xsd:element name="Run" type="Run_t"/> + </xsd:sequence> + <xsd:attribute name="Sport" type="Sport_t" use="required"/> + </xsd:complexType> + <xsd:simpleType name="Sport_t"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="Running"/> + <xsd:enumeration value="Biking"/> + <xsd:enumeration value="Other"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="Run_t"> + <xsd:sequence> + <xsd:element name="Lap" type="ActivityLap_t" maxOccurs="unbounded"/> + <xsd:element name="Notes" type="xsd:string" minOccurs="0"/> + <xsd:element name="Training" type="Training_t" minOccurs="0"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="Training_t"> + <xsd:sequence> + <xsd:element name="QuickWorkoutResults" type="QuickWorkout_t" minOccurs="0"/> + <xsd:element name="Plan" type="Plan_t" minOccurs="0"/> + </xsd:sequence> + <xsd:attribute name="VirtualPartner" type="xsd:boolean" use="required"/> + </xsd:complexType> + <xsd:complexType name="QuickWorkout_t"> + <xsd:sequence> + <xsd:element name="TotalTimeSeconds" type="xsd:double"/> + <xsd:element name="DistanceMeters" type="xsd:double"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="Plan_t"> + <xsd:sequence> + <xsd:element name="Name" type="RestrictedToken_t" minOccurs="0"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + <xsd:attribute name="Type" type="TrainingType_t" use="required"/> + <xsd:attribute name="IntervalWorkout" type="xsd:boolean" use="required"/> + </xsd:complexType> + <xsd:simpleType name="TrainingType_t"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="Workout"/> + <xsd:enumeration value="Course"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="ActivityLap_t"> + <xsd:sequence> + <xsd:element name="TotalTimeSeconds" type="xsd:double"/> + <xsd:element name="DistanceMeters" type="xsd:double"/> + <xsd:element name="MaximumSpeed" type="xsd:double" minOccurs="0"/> + <xsd:element name="Calories" type="xsd:unsignedShort"/> + <xsd:element name="AverageHeartRateBpm" type="xsd:unsignedByte" minOccurs="0"/> + <xsd:element name="MaximumHeartRateBpm" type="xsd:unsignedByte" minOccurs="0"/> + <xsd:element name="Intensity" type="Intensity_t"/> + <xsd:element name="Cadence" type="xsd:unsignedByte" minOccurs="0"/> + <xsd:element name="TriggerMethod" type="TriggerMethod_t"/> + <xsd:element name="Track" type="Track_t" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="Notes" type="xsd:string" minOccurs="0"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + <xsd:attribute name="StartTime" type="xsd:dateTime" use="required"/> + </xsd:complexType> + <xsd:simpleType name="TriggerMethod_t"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="Manual"/> + <xsd:enumeration value="Distance"/> + <xsd:enumeration value="Location"/> + <xsd:enumeration value="Time"/> + <xsd:enumeration value="HeartRate"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="Track_t"> + <xsd:sequence> + <xsd:element name="Trackpoint" type="Trackpoint_t" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="Trackpoint_t"> + <xsd:sequence> + <xsd:element name="Time" type="xsd:dateTime"/> + <xsd:element name="Position" type="Position_t" minOccurs="0"/> + <xsd:element name="AltitudeMeters" type="xsd:double" minOccurs="0"/> + <xsd:element name="DistanceMeters" type="xsd:double" minOccurs="0"/> + <xsd:element name="HeartRateBpm" type="xsd:unsignedByte" minOccurs="0"/> + <xsd:element name="Cadence" type="xsd:unsignedByte" minOccurs="0"/> + <xsd:element name="SensorState" type="SensorState_t" minOccurs="0"/> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="Position_t"> + <xsd:sequence> + <xsd:element name="LatitudeDegrees" type="DegreesLatitude_t"/> + <xsd:element name="LongitudeDegrees" type="DegreesLongitude_t"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="DegreesLongitude_t"> + <xsd:annotation> + <xsd:documentation/> + </xsd:annotation> + <xsd:restriction base="xsd:double"> + <xsd:maxExclusive value="180.0"/> + <xsd:minInclusive value="-180.0"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="DegreesLatitude_t"> + <xsd:annotation> + <xsd:documentation/> + </xsd:annotation> + <xsd:restriction base="xsd:double"> + <xsd:maxInclusive value="90.0"/> + <xsd:minInclusive value="-90.0"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="SensorState_t"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="Present"/> + <xsd:enumeration value="Absent"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="Workouts_t"> + <xsd:sequence> + <xsd:element name="Running" type="WorkoutFolder_t"> + <xsd:unique name="RunningSubFolderNamesMustBeUnique"> + <xsd:selector xpath="tc1:Folder"/> + <xsd:field xpath="@Name"/> + </xsd:unique> + </xsd:element> + <xsd:element name="Biking" type="WorkoutFolder_t"> + <xsd:unique name="BikingSubFolderNamesMustBeUnique"> + <xsd:selector xpath="tc1:Folder"/> + <xsd:field xpath="@Name"/> + </xsd:unique> + </xsd:element> + <xsd:element name="Other" type="WorkoutFolder_t"> + <xsd:unique name="OtherSubFolderNamesMustBeUnique"> + <xsd:selector xpath="tc1:Folder"/> + <xsd:field xpath="@Name"/> + </xsd:unique> + </xsd:element> + <xsd:element name="Extensions" type="Extensions_t" minOccurs="0"> + <xsd:annotation> + <xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="WorkoutFolder_t"> + <xsd:sequence> + <xsd:element name="Folder" type="WorkoutFolder_t" minOccurs="0" maxOccurs="unbounded"> + <xsd:unique name="SubFolderNamesMustBeUnique"> + <xsd:selector xpath="tc1:Folder"/> + <xsd:field xpath="@Name"/> + </xsd:unique> + </xsd:ele... [truncated message content] |
From: <jb...@us...> - 2009-09-25 10:22:15
|
Revision: 360 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=360&view=rev Author: jblance Date: 2009-09-25 10:22:03 +0000 (Fri, 25 Sep 2009) Log Message: ----------- More revisions for alt plugin branch. Garmin GPX and Garmin HR File plugins working Modified Paths: -------------- pytrainer/branches/plugins-v2/plugins/garmin-gpx/conf.xml pytrainer/branches/plugins-v2/plugins/garmin-hr-file/garminhrfile.py pytrainer/branches/plugins-v2/pytrainer/main.py pytrainer/branches/plugins-v2/pytrainer/plugins.py Added Paths: ----------- pytrainer/branches/plugins-v2/plugins/garmin-gpx/ pytrainer/branches/plugins-v2/plugins/garmin-gpx/garmingpx.py pytrainer/branches/plugins-v2/plugins/garmin-hr-file/translate.xsl pytrainer/branches/plugins-v2/pytrainer/gui/dialogs.py Removed Paths: ------------- pytrainer/branches/plugins-v2/plugins/garmin-gpx/main.py pytrainer/branches/plugins-v2/plugins/garmingpx/ Property changes on: pytrainer/branches/plugins-v2/plugins/garmin-gpx ___________________________________________________________________ Added: svn:mergeinfo + /pytrainer/trunk/plugins/garmingpx:345-347 Modified: pytrainer/branches/plugins-v2/plugins/garmin-gpx/conf.xml =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmingpx/conf.xml 2009-09-23 12:18:36 UTC (rev 358) +++ pytrainer/branches/plugins-v2/plugins/garmin-gpx/conf.xml 2009-09-25 10:22:03 UTC (rev 360) @@ -4,7 +4,7 @@ description="Import your records directly from a garmin gpx file." plugincode="garmingpx" pluginbutton="Import from Garmin GPX file" - executable="main" + executable="garmingpx" > <!--<conf-values variable="device" value="/dev/ttyUSB0"/>--> </pytrainer-plugin> Copied: pytrainer/branches/plugins-v2/plugins/garmin-gpx/garmingpx.py (from rev 358, pytrainer/branches/plugins-v2/plugins/garmingpx/main.py) =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-gpx/garmingpx.py (rev 0) +++ pytrainer/branches/plugins-v2/plugins/garmin-gpx/garmingpx.py 2009-09-25 10:22:03 UTC (rev 360) @@ -0,0 +1,63 @@ +#!/usr/bin/env python + +#Copyright (C) + +#Based on plugin by Kevin Dwyer ke...@ph... + +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either version 2 +#of the License, or (at your option) any later version. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. + +#You should have received a copy of the GNU General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import logging +from gui.dialogs import fileChooserDialog, guiFlush +import xml.etree.cElementTree + +class garmingpx(): + """ Plugin to import from a GPX file or files + Expects only one activity in each file + Checks to see if any entries are in the database with the same start time + """ + def __init__(self, parent = None): + self.parent = parent + self.tmpdir = self.parent.conf.getValue("tmpdir") + + def run(self): + selectedFiles = fileChooserDialog(title="Choose a GPX file (or files) to import", multiple=True).getFiles() + guiFlush() + importFiles = [] + for filename in selectedFiles: + if not self.inDatabase(filename): + importFiles.append(filename) + else: + print "%s already in database. Skipping import." % (filename,) + logging.debug("%s already in database. Skipping import." % (filename,) ) + return importFiles + + def inDatabase(self, filename): + #comparing date and start time (sport may have been changed in DB after import) + time = self.detailsFromGPX(filename) + if self.parent.parent.ddbb.select("records","*","date_time_utc=\"%s\"" % (time)): + return True + else: + return False + + def detailsFromGPX(self, filename): + tree = xml.etree.cElementTree.ElementTree(file=filename) + root = tree.getroot() + timeElement = root.find(".//{http://www.topografix.com/GPX/1/1}time") + if timeElement is None: + return None + else: + return timeElement.text + + Property changes on: pytrainer/branches/plugins-v2/plugins/garmin-gpx/garmingpx.py ___________________________________________________________________ Added: svn:mergeinfo + Deleted: pytrainer/branches/plugins-v2/plugins/garmin-gpx/main.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmingpx/main.py 2009-09-23 12:18:36 UTC (rev 358) +++ pytrainer/branches/plugins-v2/plugins/garmin-gpx/main.py 2009-09-25 10:22:03 UTC (rev 360) @@ -1,37 +0,0 @@ -#!/usr/bin/env python - -#Copyright (C) Kevin Dwyer ke...@ph... - -#This program is free software; you can redistribute it and/or -#modify it under the terms of the GNU General Public License -#as published by the Free Software Foundation; either version 2 -#of the License, or (at your option) any later version. - -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. - -#You should have received a copy of the GNU General Public License -#along with this program; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -import os - -class garmingpx(): - def __init__(self, parent = None): - self.parent = parent - self.tmpdir = self.parent.conf.getValue("tmpdir") - - def run(self): - # Kind of lame to shell out for this.... - f = os.popen("zenity --file-selection --multiple --title 'Choose a GPX file to import'") - inputData = f.read().strip() - inputfiles = inputData.split('|') - - rv = f.close() - if rv: - if os.WEXITSTATUS(rv) != 0: - raise Exception() - - return inputfiles Modified: pytrainer/branches/plugins-v2/plugins/garmin-hr-file/garminhrfile.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr-file/garminhrfile.py 2009-09-25 02:17:43 UTC (rev 359) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr-file/garminhrfile.py 2009-09-25 10:22:03 UTC (rev 360) @@ -1,8 +1,10 @@ #!/usr/bin/python # -*- coding: iso-8859-1 -*- -#Copyright (C) Fiz Vazquez vu...@si... +#Copyright (C) +#Based on plugin by Fiz Vazquez vu...@si... + #This program is free software; you can redistribute it and/or #modify it under the terms of the GNU General Public License #as published by the Free Software Foundation; either version 2 @@ -19,68 +21,70 @@ import os import logging -import commands +from lxml import etree -from lib.xmlUtils import XMLParser -from lib.gpx import Gpx +from gui.dialogs import fileChooserDialog, guiFlush + class garminhrfile(): + """ Plugin to import from a Garmin Training Center (version 1) file (as outputed from gpsbabel) + Can have multiple activities in the file + Checks to each activity to see if any entries are in the database with the same start time + Creates GPX files for each activity not in the database + + Note: using lxml see http://codespeak.net/lxml + """ def __init__(self, parent = None): self.parent = parent self.tmpdir = self.parent.conf.getValue("tmpdir") + self.data_path = os.path.dirname(__file__) def run(self): - f = os.popen("zenity --file-selection --title 'Choose a Garmin Training Center file to import'") - gtrnctrFile = f.read().strip() + selectedFiles = fileChooserDialog(title="Choose a Garmin Training Center file to import").getFiles() + guiFlush() + importfiles = [] + if not selectedFiles: + return importfiles + for filename in selectedFiles: #could be multiple files selected - currently only single selection enabled + tracks = self.getTracks(filename) + logging.debug("Found %d tracks in %s" % (len(tracks), filename)) + for track in tracks: #can be multiple tracks + if shouldImport(track): + gpxfile = "%s/garminhrfile%d.gpx" % (self.tmpdir, len(importfiles)) + self.createGPXfile(gpxfile, track) + importfiles.append(gpxfile) + return importfiles - # XML file from gpsbabel refers to schemas and namespace definitions which are no longer available, removing this info - dgg - 12.05.2008 - # check to see if we can remove this... - gtrnctrFileMod = removeHeaders(gtrnctrFile) - print "modified gtrnctrfile: " + gtrnctrFileMod - - return [gtrnctrFileMod,] #TODO this is where the conversion and checking will occur - - def removeHeaders(gtrnctrFile): - if os.path.isfile(gtrnctrFile): - gtrnctrFileMod = self.tmpdir+"/file_mod.gtrnctr" - f = open(gtrnctrFile,"r") - lines = f.readlines() - f.close() - f = open(gtrnctrFileMod,'w') - headers = lines[0]+'<TrainingCenterDatabase>\n' - f.write(headers) - f.write(''.join(lines[6:])) - f.close() - return gtrnctrFileMod + def shouldImport(self, track): + """ Function determines whether a track should be imported or not + Currently using time only + """ + timeElement = track.find(".//{http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v1}Time") + if timeElement is None: + #print (etree.tostring(track, pretty_print=True)) + logging.debug("Error no time found in track") + return False + else: + time = timeElement.text + #comparing date and start time (sport may have been changed in DB after import) + if self.parent.parent.ddbb.select("records","*","date_time_utc=\"%s\"" % (time)): + return True else: - return None + return False - def importFromGTRNCTR(self,gtrnctrFile): - """22.03.2008 - dgranda - Retrieves sport, date and start time from each entry coming from GPS - and compares with what is stored locally, just to import new entries - 31.08.2008 - dgranda - Only checks start time, discarding sport info - args: file with data from GPS file (garmin format) - returns: none""" - logging.debug('>>') - logging.info('Retrieving data from '+gtrnctrFile) - xmlParser=XMLParser(gtrnctrFile) - listTracksGPS = xmlParser.shortFromGPS(gtrnctrFile, True) - logging.info('GPS: '+str(len(listTracksGPS))+' entries found') - if len(listTracksGPS)>0: - listTracksLocal = self.shortFromLocalDB(True) - logging.info('Local: '+str(len(listTracksLocal))+' entries found') - listNewTracks=self.compareTracks(listTracksGPS,listTracksLocal,False) - newTracks = len(listNewTracks) - # empty constructor for Gpx - gpx = Gpx() - i=0 - for entry in listNewTracks: - i=i+1 - logging.debug('Entry summary to import: '+str(entry)) - newGPX=gpx.retrieveDataFromGTRNCTR(gtrnctrFile, entry) - entry_id = self.insertNewRecord(newGPX, entry) - logging.info('Entry '+str(entry_id)+' has been added ('+str(i)+'/'+str(newTracks)+')') - else: - logging.info('No tracks found in GPS device') - logging.debug('<<') + def getTracks(self, filename): + """ Function to return all the tracks in a Garmin Training Center v1 file + """ + tree = etree.ElementTree(file=filename) + root = tree.getroot() + tracks = root.findall(".//{http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v1}Track") + return tracks + + def createGPXfile(self, gpxfile, track): + """ Function to transform a Garmin Training Center v1 Track to a valid GPX file + """ + xslt_doc = etree.parse(self.data_path+"/translate.xsl") + transform = etree.XSLT(xslt_doc) + result_tree = transform(track) + result_tree.write(gpxfile) + Added: pytrainer/branches/plugins-v2/plugins/garmin-hr-file/translate.xsl =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr-file/translate.xsl (rev 0) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr-file/translate.xsl 2009-09-25 10:22:03 UTC (rev 360) @@ -0,0 +1,58 @@ +<?xml version="1.0"?> + +<!-- note defining a namespace for TrainingCenterDatabase as the translation does not seem to work with a default namespace --> +<xsl:stylesheet version="1.0" +xmlns:t="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v1" +xmlns:xsl="http://www.w3.org/1999/XSL/Transform" +> +<xsl:output method="xml" indent="yes" omit-xml-declaration="no"/> + +<!-- this is a bit of a messy way to get whitespace into the output - but it works --> +<xsl:variable name="newline"><xsl:text> +</xsl:text></xsl:variable> + +<xsl:template match="/"> + <gpx xmlns="http://www.topografix.com/GPX/1/1" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:gpxdata="http://www.cluetrust.com/XML/GPXDATA/1/0" + creator="pytrainer http://sourceforge.net/projects/pytrainer" version="1.1" + xsi:schemaLocation="http://www.topografix.com/GPX/1/1 + http://www.topografix.com/GPX/1/1/gpx.xsd + http://www.cluetrust.com/XML/GPXDATA/1/0 + http://www.cluetrust.com/Schemas/gpxdata10.xsd"> + + <xsl:value-of select="$newline"/> + <xsl:variable name="sport">"Run"</xsl:variable> + <xsl:variable name="time"><xsl:value-of select="t:Track/t:Trackpoint/t:Time"/></xsl:variable> + <xsl:variable name="name"><xsl:value-of select="$sport"/><xsl:value-of select="substring($time, 1,10)"/></xsl:variable> + <metadata><xsl:value-of select="$newline"/> + <name><xsl:value-of select="$name"/></name><xsl:value-of select="$newline"/> + <link href="http://sourceforge.net/projects/pytrainer"/><xsl:value-of select="$newline"/> + <time><xsl:value-of select="$time"/></time><xsl:value-of select="$newline"/> + </metadata><xsl:value-of select="$newline"/> + <trk><xsl:value-of select="$newline"/> + <xsl:for-each select="t:Track"> + <trkseg><xsl:value-of select="$newline"/> + <xsl:for-each select="t:Trackpoint"> + <!-- only output a trkpt if a position exists --> + <xsl:if test="t:Position"> + <xsl:variable name="lat"><xsl:value-of select="t:Position/t:LatitudeDegrees"/></xsl:variable> + <xsl:variable name="lon"><xsl:value-of select="t:Position/t:LongitudeDegrees"/></xsl:variable> + <trkpt lat="{$lat}" lon="{$lon}"><xsl:value-of select="$newline"/> + <ele><xsl:value-of select="t:AltitudeMeters"/></ele><xsl:value-of select="$newline"/> + <time><xsl:value-of select="t:Time"/></time><xsl:value-of select="$newline"/> + <xsl:if test="t:HeartRateBpm/t:Value"> + <extensions><xsl:value-of select="$newline"/> + <gpxdata:hr><xsl:value-of select="t:HeartRateBpm/t:Value"/></gpxdata:hr><xsl:value-of select="$newline"/> + </extensions><xsl:value-of select="$newline"/> + </xsl:if> + </trkpt><xsl:value-of select="$newline"/> + </xsl:if> + </xsl:for-each> + <xsl:value-of select="$newline"/> + </trkseg><xsl:value-of select="$newline"/> + </xsl:for-each> + </trk><xsl:value-of select="$newline"/> + </gpx><xsl:value-of select="$newline"/> +</xsl:template> +</xsl:stylesheet> Added: pytrainer/branches/plugins-v2/pytrainer/gui/dialogs.py =================================================================== --- pytrainer/branches/plugins-v2/pytrainer/gui/dialogs.py (rev 0) +++ pytrainer/branches/plugins-v2/pytrainer/gui/dialogs.py 2009-09-25 10:22:03 UTC (rev 360) @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +#Copyright (C) + +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either version 2 +#of the License, or (at your option) any later version. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. + +#You should have received a copy of the GNU General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import os +import pygtk +pygtk.require('2.0') +import gtk + +class fileChooserDialog(): + def __init__(self, title = "Choose a file", multiple = False): + dialog = gtk.FileChooserDialog(title, None, gtk.FILE_CHOOSER_ACTION_OPEN,(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) + dialog.set_default_response(gtk.RESPONSE_OK) + dialog.set_select_multiple(multiple) + response = dialog.run() + if response == gtk.RESPONSE_OK: + self.inputfiles = dialog.get_filenames() + elif response == gtk.RESPONSE_CANCEL: + self.inputfiles = None + dialog.destroy() + + def getFiles(self): + return self.inputfiles + +class guiFlush(): + def __init__(self): + dialog = gtk.Dialog(title=None, parent=None, flags=0, buttons=None) + dialog.show() + dialog.destroy() + + + + Modified: pytrainer/branches/plugins-v2/pytrainer/main.py =================================================================== --- pytrainer/branches/plugins-v2/pytrainer/main.py 2009-09-25 02:17:43 UTC (rev 359) +++ pytrainer/branches/plugins-v2/pytrainer/main.py 2009-09-25 10:22:03 UTC (rev 360) @@ -88,7 +88,8 @@ self.data_path = data_path self.version ="1.6.0.9" # 22.10.2009 self.date = Date() - + main_dir = os.path.realpath(os.path.dirname(__file__)) #why? + sys.path.insert(0, main_dir) #why? # Checking profile self.profile = Profile(self.data_path,self) #self.profile.setVersion("0.0") @@ -117,7 +118,7 @@ self.waypoint = Waypoint(data_path,self) self.extension = Extension(data_path) - self.plugins = Plugins(data_path) + self.plugins = Plugins(data_path, self) self.loadPlugins() self.loadExtensions() self.windowmain.createGraphs(RecordGraph,DayGraph,MonthGraph,YearGraph,HeartRateGraph) @@ -162,14 +163,17 @@ logging.debug('>>') self.pluginClass = self.plugins.importClass(pathPlugin) pluginFiles = self.pluginClass.run() - logging.debug("Plugin returned " +str(len(pluginFiles)) + " files: " +','.join(pluginFiles) ) - #process returned GPX files - for pluginFile in pluginFiles: - if os.path.isfile(pluginFile): - logging.info('File exists. Size: '+ str(os.path.getsize(pluginFile))) - self.record.importFromGPX(pluginFile) - else: - logging.error('File '+pluginFile+' not valid') + if pluginFiles is not None: + logging.debug("Plugin returned " +str(len(pluginFiles)) + " files: " +','.join(pluginFiles) ) + #process returned GPX files + for pluginFile in pluginFiles: + if os.path.isfile(pluginFile): + logging.info('File exists. Size: '+ str(os.path.getsize(pluginFile))) + self.record.importFromGPX(pluginFile) + else: + logging.error('File '+pluginFile+' not valid') + else: + logging.debug("No files returned from Plugin") logging.debug('<<') def runExtension(self,extension,id): Modified: pytrainer/branches/plugins-v2/pytrainer/plugins.py =================================================================== --- pytrainer/branches/plugins-v2/pytrainer/plugins.py 2009-09-25 02:17:43 UTC (rev 359) +++ pytrainer/branches/plugins-v2/pytrainer/plugins.py 2009-09-25 10:22:03 UTC (rev 360) @@ -26,9 +26,10 @@ from gui.windowplugins import WindowPlugins class Plugins: - def __init__(self, data_path = None): + def __init__(self, data_path = None, parent = None): self.data_path=data_path self.conf = checkConf() + self.parent = parent def getActivePlugins(self): retorno = [] @@ -57,8 +58,8 @@ logging.debug("Plugin Classname: " + plugin_classname) sys.path.insert(0, plugin_dir) module = __import__(plugin_filename) + pluginMain = getattr(module, plugin_classname) logging.debug('<<') - pluginMain = getattr(module, plugin_classname) return pluginMain(self) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-09-25 02:17:53
|
Revision: 359 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=359&view=rev Author: jblance Date: 2009-09-25 02:17:43 +0000 (Fri, 25 Sep 2009) Log Message: ----------- Add plugin for testing import from TCXv1 Modified Paths: -------------- pytrainer/branches/plugins-v2/plugins/garmin-hr-file/conf.xml pytrainer/branches/plugins-v2/plugins/garmingpx/main.py Added Paths: ----------- pytrainer/branches/plugins-v2/plugins/garmin-hr/ pytrainer/branches/plugins-v2/plugins/garmin-hr/conf.xml pytrainer/branches/plugins-v2/plugins/garmin-hr/gtrnctr2gpx.py pytrainer/branches/plugins-v2/plugins/garmin-hr/main.py pytrainer/branches/plugins-v2/plugins/garmin-hr/pytrainer.style pytrainer/branches/plugins-v2/plugins/garmin-hr-file/ Removed Paths: ------------- pytrainer/branches/plugins-v2/plugins/garmin-hr/ Copied: pytrainer/branches/plugins-v2/plugins/garmin-hr/conf.xml (from rev 358, pytrainer/trunk/plugins/garmin-hr/conf.xml) =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr/conf.xml (rev 0) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr/conf.xml 2009-09-25 02:17:43 UTC (rev 359) @@ -0,0 +1,10 @@ +<?xml version="1.0" ?> +<pytrainer-plugin + name="Garmin Heart Rate" + description="Import yor records direclty from your garmin gps device with heart rate support" + plugincode="garmin-hr" + pluginbutton="Import from Garmin (HR support)" + executable="main.py" +> +<conf-values variable="device" value="usb:"/> +</pytrainer-plugin> Property changes on: pytrainer/branches/plugins-v2/plugins/garmin-hr/conf.xml ___________________________________________________________________ Added: svn:mergeinfo + Copied: pytrainer/branches/plugins-v2/plugins/garmin-hr/gtrnctr2gpx.py (from rev 358, pytrainer/trunk/plugins/garmin-hr/gtrnctr2gpx.py) =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr/gtrnctr2gpx.py (rev 0) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr/gtrnctr2gpx.py 2009-09-25 02:17:43 UTC (rev 359) @@ -0,0 +1,82 @@ +#!/usr/bin/python +# -*- coding: iso-8859-1 -*- + +#Copyright (C) Fiz Vazquez vu...@si... + +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either version 2 +#of the License, or (at your option) any later version. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. + +#You should have received a copy of the GNU General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +import sys + +import xml.dom.minidom + +#the _variables are the gpx ones. The variables are the xcsv one + + +def gtrnctr2gpx(gtrnctrfile,gpxfile): + dom = xml.dom.minidom.parse(gtrnctrfile) + d = xml.dom.minidom.getDOMImplementation() + _dom = d.createDocument(None,"gpx",None) + _gpx_element = _dom.documentElement + _gpx_element.setAttribute('creator',"pytrainer http://pytrainer.e-oss.net") + _gpx_element.setAttribute('version',"1.1") + _gpx_element.setAttribute('xmlns',"http://www.topografix.com/GPX/1/1") + _gpx_element.setAttribute('xmlns:geocache',"http://www.groundspeak.com/cache/1/0") + _gpx_element.setAttribute('xmlns:gpxdata',"http://www.cluetrust.com/XML/GPXDATA/1/0") + _gpx_element.setAttribute('xmlns:xsi',"http://www.w3.org/2001/XMLSchema-instance") + _gpx_element.setAttribute('xsi:schemaLocation',"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.cluetrust.com/XML/GPXDATA/1/0 http://www.cluetrust.com/Schemas/gpxdata10.xsd") + + trks = dom.getElementsByTagName("Track") + nametrack = 0 + for trk in trks: + nametrack = nametrack+1 + _trk = _dom.createElement("trk") + _name = _dom.createElement("name") + _name.appendChild(_dom.createTextNode("%s"%str(nametrack))) + _trk.appendChild(_name) + trkpoints = trk.getElementsByTagName("Trackpoint") + for trkpoint in trkpoints: + _trkpt = _dom.createElement("trkpt") + time = trkpoint.getElementsByTagName("Time")[0].firstChild.data + alt = trkpoint.getElementsByTagName("AltitudeMeters")[0].firstChild.data + if len(trkpoint.getElementsByTagName("HeartRateBpm"))>0: + hr = trkpoint.getElementsByTagName("HeartRateBpm")[0].firstChild.data + else: + hr = "0" + lat = trkpoint.getElementsByTagName("LatitudeDegrees")[0].firstChild.data + lon = trkpoint.getElementsByTagName("LongitudeDegrees")[0].firstChild.data + + _time = _dom.createElement("time") + _ele = _dom.createElement("ele") + _hr = _dom.createElement("gpxdata:hr") + _extensions = _dom.createElement("extensions") + _time.appendChild(_dom.createTextNode(time)) + _ele.appendChild(_dom.createTextNode(alt)) + _hr.appendChild(_dom.createTextNode(hr)) + _extensions.appendChild(_hr) + _trkpt.appendChild(_time) + _trkpt.appendChild(_ele) + _trkpt.appendChild(_extensions) + _trkpt.setAttribute('lat', lat) + _trkpt.setAttribute('lon', lon) + _trk.appendChild(_trkpt) + _gpx_element.appendChild(_trk) + + f = open(gpxfile, 'w') + #_dom.writexml(f) + #f.write(_dom.toprettyxml()) + f.write(_dom.toxml()) + f.close() + Property changes on: pytrainer/branches/plugins-v2/plugins/garmin-hr/gtrnctr2gpx.py ___________________________________________________________________ Added: svn:mergeinfo + Copied: pytrainer/branches/plugins-v2/plugins/garmin-hr/main.py (from rev 358, pytrainer/trunk/plugins/garmin-hr/main.py) =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr/main.py (rev 0) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr/main.py 2009-09-25 02:17:43 UTC (rev 359) @@ -0,0 +1,63 @@ +#!/usr/bin/python +# -*- coding: iso-8859-1 -*- + +#Copyright (C) Fiz Vazquez vu...@si... + +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either version 2 +#of the License, or (at your option) any later version. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. + +#You should have received a copy of the GNU General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +from optparse import OptionParser +#from gtrnctr2gpx import gtrnctr2gpx +import os +import commands + +parser = OptionParser() +parser.add_option("-d", "--device", dest="device") +(options,args) = parser.parse_args() +gtrnctrFile="/tmp/file.gtrnctr" +gtrnctrFileMod="/tmp/file_mod.gtrnctr" +input_dev = options.device + +# ToDo (19.05.2008): better exception handling +try: + outmod = commands.getstatusoutput('/sbin/lsmod | grep garmin_gps') + #os.popen("zenity --error --text='Devuelve: %s'" %str(outmod)) + if outmod[0]==256: #there is no garmin_gps module loaded + input_dev = "usb:" + else: + raise Exception + # Can't export to GPX directly because lack of support for heartrate and sports (1.0 version, may change when gpsbabel supports 1.1 with custom fields) + outgps = commands.getstatusoutput("gpsbabel -t -i garmin -f %s -o gtrnctr -F /tmp/file.gtrnctr | zenity --progress --pulsate --text='Loading Data' auto-close" %input_dev) + #os.popen("zenity --error --text='Devuelve: %s'" %str(outgps)) + # XML file from gpsbabel refers to schemas and namespace definitions which are no longer available, removing this info - dgg - 12.05.2008 + if outgps[0]==0: + if outgps[1] == "Found no Garmin USB devices.": # check localizations + raise Exception + else: + if os.path.isfile(gtrnctrFile): + f = open(gtrnctrFile,"r") + lines = f.readlines() + f.close() + f = open(gtrnctrFileMod,'w') + headers = lines[0]+'<TrainingCenterDatabase>\n' + f.write(headers) + f.write(''.join(lines[6:])) + f.close() + print gtrnctrFileMod + else: + raise Exception +except Exception: + os.popen("zenity --error --text='Can not handle Garmin device\nCheck your configuration\nCurrent usb port is set to:\t %s'" %input_dev); + Property changes on: pytrainer/branches/plugins-v2/plugins/garmin-hr/main.py ___________________________________________________________________ Added: svn:executable + * Added: svn:mergeinfo + Copied: pytrainer/branches/plugins-v2/plugins/garmin-hr/pytrainer.style (from rev 358, pytrainer/trunk/plugins/garmin-hr/pytrainer.style) =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr/pytrainer.style (rev 0) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr/pytrainer.style 2009-09-25 02:17:43 UTC (rev 359) @@ -0,0 +1,39 @@ +# gpsbabel XCSV style file +# +# Format: GPSDrive +# Author: Alex Mottram +# Date: 12/11/2002 +# +# +# + +DESCRIPTION GpsDrive Format +DATATIPE TRACK + +# FILE LAYOUT DEFINITIIONS: +# +FIELD_DELIMITER WHITESPACE +RECORD_DELIMITER CRNEWLINE +BADCHARS WHITESPACE +PROLOGUE OziExplorer Waypoint File Version 1.1 + +SHORTLEN 20 +SHORTWHITE 0 + +# +# INDIVIDUAL DATA FIELDS, IN ORDER OF APPEARANCE: + +IFIELD SHORTNAME, "", "%s" +IFIELD LAT_DECIMAL, "", "%08.5f" +IFIELD LON_DECIMAL, "", "%08.5f" +IFIELD ALT_METERS, "", "%.0f" +IFIELD GMT_TIME,"","%m/%d/%Y %I:%M:%D %p" +IFIELD ICON_DESCR, "", "%s" +IFIELD TRACK_NAME, "", "%s" + +#OFIELD TRACK_NAME, "", "%s" +OFIELD LAT_DECIMAL, "", "%08.5f" +OFIELD LON_DECIMAL, "", "%08.5f" +OFIELD ALT_METERS, "", "%.0f" +OFIELD GMT_TIME,"","%s" +OFIELD HEART_RATE,"","%d" Property changes on: pytrainer/branches/plugins-v2/plugins/garmin-hr/pytrainer.style ___________________________________________________________________ Added: svn:mergeinfo + Property changes on: pytrainer/branches/plugins-v2/plugins/garmin-hr-file ___________________________________________________________________ Added: svn:mergeinfo + /pytrainer/trunk/plugins/garmin-hr:345-347 Modified: pytrainer/branches/plugins-v2/plugins/garmin-hr-file/conf.xml =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr/conf.xml 2009-09-23 12:18:36 UTC (rev 358) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr-file/conf.xml 2009-09-25 02:17:43 UTC (rev 359) @@ -1,7 +1,7 @@ <?xml version="1.0" ?> <pytrainer-plugin - name="Garmin Heart Rate" - description="Import records from a garmin gps device with heart rate support (from a file)" + name="Garmin Import with HR (from TCXv1file)" + description="Import records from a garmin gps device with heart rate support (from TCXv1 file)" plugincode="garminhrfile" pluginbutton="Import from Garmin file (HR support)" executable="garminhrfile" Modified: pytrainer/branches/plugins-v2/plugins/garmingpx/main.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmingpx/main.py 2009-09-23 12:18:36 UTC (rev 358) +++ pytrainer/branches/plugins-v2/plugins/garmingpx/main.py 2009-09-25 02:17:43 UTC (rev 359) @@ -17,6 +17,7 @@ #Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. import os +import lib.fileSelector class garmingpx(): def __init__(self, parent = None): @@ -25,6 +26,8 @@ def run(self): # Kind of lame to shell out for this.... + f = FileSelectionDialog( ) + return f = os.popen("zenity --file-selection --multiple --title 'Choose a GPX file to import'") inputData = f.read().strip() inputfiles = inputData.split('|') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-09-23 13:22:31
|
Revision: 358 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=358&view=rev Author: jblance Date: 2009-09-23 12:18:36 +0000 (Wed, 23 Sep 2009) Log Message: ----------- Reverting Googleearth plugin Modified Paths: -------------- pytrainer/trunk/plugins/googleearth/conf.xml Modified: pytrainer/trunk/plugins/googleearth/conf.xml =================================================================== --- pytrainer/trunk/plugins/googleearth/conf.xml 2009-09-23 12:06:44 UTC (rev 357) +++ pytrainer/trunk/plugins/googleearth/conf.xml 2009-09-23 12:18:36 UTC (rev 358) @@ -1,9 +1,9 @@ <?xml version="1.0" ?> <pytrainer-plugin - name="Garmin v2 TCX" - description="Import your records from a version 2 TCX file from a Garmin gps device (i.e. Forerunner 405)" - plugincode="garminTCXv2" - pluginbutton="Import from Garmin TCX (version 2)" - executable="garmin-tcxv2" + name="Google Earth" + description="Import yor Google Earth files (*.kml)" + plugincode="googleearth" + pluginbutton="Import Google Earth File (*.kml)" + executable="main.sh" > </pytrainer-plugin> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-09-23 12:06:55
|
Revision: 357 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=357&view=rev Author: jblance Date: 2009-09-23 12:06:44 +0000 (Wed, 23 Sep 2009) Log Message: ----------- Fixing up a messy plugin commit Added Paths: ----------- pytrainer/trunk/plugins/googleearth/main.sh Removed Paths: ------------- pytrainer/trunk/plugins/googleearth/garmin-tcxv2.py pytrainer/trunk/plugins/googleearth/garmin-tcxv2.pyc pytrainer/trunk/plugins/googleearth/translate.xsl Deleted: pytrainer/trunk/plugins/googleearth/garmin-tcxv2.py =================================================================== --- pytrainer/trunk/plugins/googleearth/garmin-tcxv2.py 2009-09-23 11:36:05 UTC (rev 356) +++ pytrainer/trunk/plugins/googleearth/garmin-tcxv2.py 2009-09-23 12:06:44 UTC (rev 357) @@ -1,57 +0,0 @@ -# -*- coding: iso-8859-1 -*- - -#Copyright (C) Fiz Vazquez vu...@si... -# Modified by dgranda - -#This program is free software; you can redistribute it and/or -#modify it under the terms of the GNU General Public License -#as published by the Free Software Foundation; either version 2 -#of the License, or (at your option) any later version. - -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. - -#You should have received a copy of the GNU General Public License -#along with this program; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -import logging -import os -import libxml2 -import libxslt - -class garminTCXv2(): - def __init__(self, parent = None): - self.parent = parent - self.tmpdir = self.parent.conf.getValue("tmpdir") - - def run(self): - logging.debug(">>") - # able to select multiple files.... - f = os.popen("zenity --file-selection --multiple --title 'Choose a TCX file to import'") - inputData = f.read().strip() - inputfiles = inputData.split('|') - xslfile= os.path.dirname(os.path.realpath(__file__)) + "/translate.xsl" - outputfile=[] - if os.path.isfile(xslfile): - for index in range(len(inputfiles)): - outputfile.append(self.tmpdir+"/outputfile"+str(index)+".gpx") - inputfile=inputfiles[index] - if os.path.isfile(inputfile): - styledoc = libxml2.parseFile(xslfile) - style = libxslt.parseStylesheetDoc(styledoc) - doc = libxml2.parseFile(inputfile) - result = style.applyStylesheet(doc, None) - style.saveResultToFilename(outputfile[index], result, 0) - style.freeStylesheet() - doc.freeDoc() - result.freeDoc() - else: - raise Exception("XML input file not found, looking for: " + inputfile) - else: - raise Exception("XSL file not found, looking for: " + xslfile) - logging.debug("<<") - return outputfile - Deleted: pytrainer/trunk/plugins/googleearth/garmin-tcxv2.pyc =================================================================== (Binary files differ) Added: pytrainer/trunk/plugins/googleearth/main.sh =================================================================== --- pytrainer/trunk/plugins/googleearth/main.sh (rev 0) +++ pytrainer/trunk/plugins/googleearth/main.sh 2009-09-23 12:06:44 UTC (rev 357) @@ -0,0 +1,26 @@ +#!/bin/sh +# -*- coding: iso-8859-1 -*- + +#Copyright (C) Fiz Vazquez vu...@si... + +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either version 2 +#of the License, or (at your option) any later version. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. + +#You should have received a copy of the GNU General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +var=`zenity --file-selection` + +tmpgpx="/tmp/reg.gpx" +gpsbabel -t -i kml -f $var -o gpx -F $tmpgpx + +echo $tmpgpx Property changes on: pytrainer/trunk/plugins/googleearth/main.sh ___________________________________________________________________ Added: svn:executable + * Deleted: pytrainer/trunk/plugins/googleearth/translate.xsl =================================================================== --- pytrainer/trunk/plugins/googleearth/translate.xsl 2009-09-23 11:36:05 UTC (rev 356) +++ pytrainer/trunk/plugins/googleearth/translate.xsl 2009-09-23 12:06:44 UTC (rev 357) @@ -1,63 +0,0 @@ -<?xml version="1.0"?> - -<!-- note defining a namespace for TrainingCenterDatabase as the translation does not seem to work with a default namespace --> -<xsl:stylesheet version="1.0" -xmlns:t="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2" -xmlns:xsl="http://www.w3.org/1999/XSL/Transform" -> -<xsl:output method="xml" indent="yes" omit-xml-declaration="no"/> - -<!-- this is a bit of a messy way to get whitespace into the output - but it works --> -<xsl:variable name="newline"><xsl:text> -</xsl:text></xsl:variable> - -<xsl:template match="/"> - <gpx xmlns="http://www.topografix.com/GPX/1/1" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:gpxdata="http://www.cluetrust.com/XML/GPXDATA/1/0" - creator="pytrainer http://sourceforge.net/projects/pytrainer" version="1.1" - xsi:schemaLocation="http://www.topografix.com/GPX/1/1 - http://www.topografix.com/GPX/1/1/gpx.xsd - http://www.cluetrust.com/XML/GPXDATA/1/0 - http://www.cluetrust.com/Schemas/gpxdata10.xsd"> - - <xsl:value-of select="$newline"/> - <xsl:variable name="sport"><xsl:value-of select="t:TrainingCenterDatabase/t:Activities/t:Activity/@Sport"/></xsl:variable> - <xsl:variable name="time"><xsl:value-of select="t:TrainingCenterDatabase/t:Activities/t:Activity/t:Id"/></xsl:variable> - <xsl:variable name="name"><xsl:value-of select="$sport"/><xsl:value-of select="substring($time, 1,10)"/></xsl:variable> - <metadata><xsl:value-of select="$newline"/> - <name><xsl:value-of select="$name"/></name><xsl:value-of select="$newline"/> - <link href="http://sourceforge.net/projects/pytrainer"/><xsl:value-of select="$newline"/> - <time><xsl:value-of select="$time"/></time><xsl:value-of select="$newline"/> - </metadata><xsl:value-of select="$newline"/> - <trk><xsl:value-of select="$newline"/> - <xsl:for-each select="t:TrainingCenterDatabase/t:Activities/t:Activity/t:Lap"> - <trkseg><xsl:value-of select="$newline"/> - <xsl:variable name="calories"><xsl:value-of select="t:Calories"/></xsl:variable> - <xsl:for-each select="t:Track/t:Trackpoint"> - <!-- only output a trkpt if a position exists --> - <xsl:if test="t:Position"> - <xsl:variable name="lat"><xsl:value-of select="t:Position/t:LatitudeDegrees"/></xsl:variable> - <xsl:variable name="lon"><xsl:value-of select="t:Position/t:LongitudeDegrees"/></xsl:variable> - <trkpt lat="{$lat}" lon="{$lon}"><xsl:value-of select="$newline"/> - <ele><xsl:value-of select="t:AltitudeMeters"/></ele><xsl:value-of select="$newline"/> - <time><xsl:value-of select="t:Time"/></time><xsl:value-of select="$newline"/> - <xsl:if test="t:HeartRateBpm/t:Value"> - <extensions><xsl:value-of select="$newline"/> - <gpxdata:hr><xsl:value-of select="t:HeartRateBpm/t:Value"/></gpxdata:hr><xsl:value-of select="$newline"/> - </extensions><xsl:value-of select="$newline"/> - </xsl:if> - </trkpt><xsl:value-of select="$newline"/> - </xsl:if> - </xsl:for-each> - <xsl:value-of select="$newline"/> - <extensions><xsl:value-of select="$newline"/> - <gpxdata:sportType><xsl:value-of select="$sport"/></gpxdata:sportType><xsl:value-of select="$newline"/> - <gpxdata:calories><xsl:value-of select="$calories"/></gpxdata:calories><xsl:value-of select="$newline"/> - </extensions><xsl:value-of select="$newline"/> - </trkseg><xsl:value-of select="$newline"/> - </xsl:for-each> - </trk><xsl:value-of select="$newline"/> - </gpx><xsl:value-of select="$newline"/> -</xsl:template> -</xsl:stylesheet> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-09-23 11:36:13
|
Revision: 356 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=356&view=rev Author: jblance Date: 2009-09-23 11:36:05 +0000 (Wed, 23 Sep 2009) Log Message: ----------- TCX v2 update Added Paths: ----------- pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/ pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/conf.xml pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/garmin-tcxv2.py pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/translate.xsl Added: pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/conf.xml =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/conf.xml (rev 0) +++ pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/conf.xml 2009-09-23 11:36:05 UTC (rev 356) @@ -0,0 +1,9 @@ +<?xml version="1.0" ?> +<pytrainer-plugin + name="Garmin v2 TCX" + description="Import your records from a version 2 TCX file from a Garmin gps device (i.e. Forerunner 405)" + plugincode="garminTCXv2" + pluginbutton="Import from Garmin TCX (version 2)" + executable="garmin-tcxv2" +> +</pytrainer-plugin> Added: pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/garmin-tcxv2.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/garmin-tcxv2.py (rev 0) +++ pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/garmin-tcxv2.py 2009-09-23 11:36:05 UTC (rev 356) @@ -0,0 +1,57 @@ +# -*- coding: iso-8859-1 -*- + +#Copyright (C) Fiz Vazquez vu...@si... +# Modified by dgranda + +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either version 2 +#of the License, or (at your option) any later version. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. + +#You should have received a copy of the GNU General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import logging +import os +import libxml2 +import libxslt + +class garminTCXv2(): + def __init__(self, parent = None): + self.parent = parent + self.tmpdir = self.parent.conf.getValue("tmpdir") + + def run(self): + logging.debug(">>") + # able to select multiple files.... + f = os.popen("zenity --file-selection --multiple --title 'Choose a TCX file to import'") + inputData = f.read().strip() + inputfiles = inputData.split('|') + xslfile= os.path.dirname(os.path.realpath(__file__)) + "/translate.xsl" + outputfile=[] + if os.path.isfile(xslfile): + for index in range(len(inputfiles)): + outputfile.append(self.tmpdir+"/outputfile"+str(index)+".gpx") + inputfile=inputfiles[index] + if os.path.isfile(inputfile): + styledoc = libxml2.parseFile(xslfile) + style = libxslt.parseStylesheetDoc(styledoc) + doc = libxml2.parseFile(inputfile) + result = style.applyStylesheet(doc, None) + style.saveResultToFilename(outputfile[index], result, 0) + style.freeStylesheet() + doc.freeDoc() + result.freeDoc() + else: + raise Exception("XML input file not found, looking for: " + inputfile) + else: + raise Exception("XSL file not found, looking for: " + xslfile) + logging.debug("<<") + return outputfile + Added: pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/translate.xsl =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/translate.xsl (rev 0) +++ pytrainer/branches/plugins-v2/plugins/garmin-tcxv2/translate.xsl 2009-09-23 11:36:05 UTC (rev 356) @@ -0,0 +1,63 @@ +<?xml version="1.0"?> + +<!-- note defining a namespace for TrainingCenterDatabase as the translation does not seem to work with a default namespace --> +<xsl:stylesheet version="1.0" +xmlns:t="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2" +xmlns:xsl="http://www.w3.org/1999/XSL/Transform" +> +<xsl:output method="xml" indent="yes" omit-xml-declaration="no"/> + +<!-- this is a bit of a messy way to get whitespace into the output - but it works --> +<xsl:variable name="newline"><xsl:text> +</xsl:text></xsl:variable> + +<xsl:template match="/"> + <gpx xmlns="http://www.topografix.com/GPX/1/1" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:gpxdata="http://www.cluetrust.com/XML/GPXDATA/1/0" + creator="pytrainer http://sourceforge.net/projects/pytrainer" version="1.1" + xsi:schemaLocation="http://www.topografix.com/GPX/1/1 + http://www.topografix.com/GPX/1/1/gpx.xsd + http://www.cluetrust.com/XML/GPXDATA/1/0 + http://www.cluetrust.com/Schemas/gpxdata10.xsd"> + + <xsl:value-of select="$newline"/> + <xsl:variable name="sport"><xsl:value-of select="t:TrainingCenterDatabase/t:Activities/t:Activity/@Sport"/></xsl:variable> + <xsl:variable name="time"><xsl:value-of select="t:TrainingCenterDatabase/t:Activities/t:Activity/t:Id"/></xsl:variable> + <xsl:variable name="name"><xsl:value-of select="$sport"/><xsl:value-of select="substring($time, 1,10)"/></xsl:variable> + <metadata><xsl:value-of select="$newline"/> + <name><xsl:value-of select="$name"/></name><xsl:value-of select="$newline"/> + <link href="http://sourceforge.net/projects/pytrainer"/><xsl:value-of select="$newline"/> + <time><xsl:value-of select="$time"/></time><xsl:value-of select="$newline"/> + </metadata><xsl:value-of select="$newline"/> + <trk><xsl:value-of select="$newline"/> + <xsl:for-each select="t:TrainingCenterDatabase/t:Activities/t:Activity/t:Lap"> + <trkseg><xsl:value-of select="$newline"/> + <xsl:variable name="calories"><xsl:value-of select="t:Calories"/></xsl:variable> + <xsl:for-each select="t:Track/t:Trackpoint"> + <!-- only output a trkpt if a position exists --> + <xsl:if test="t:Position"> + <xsl:variable name="lat"><xsl:value-of select="t:Position/t:LatitudeDegrees"/></xsl:variable> + <xsl:variable name="lon"><xsl:value-of select="t:Position/t:LongitudeDegrees"/></xsl:variable> + <trkpt lat="{$lat}" lon="{$lon}"><xsl:value-of select="$newline"/> + <ele><xsl:value-of select="t:AltitudeMeters"/></ele><xsl:value-of select="$newline"/> + <time><xsl:value-of select="t:Time"/></time><xsl:value-of select="$newline"/> + <xsl:if test="t:HeartRateBpm/t:Value"> + <extensions><xsl:value-of select="$newline"/> + <gpxdata:hr><xsl:value-of select="t:HeartRateBpm/t:Value"/></gpxdata:hr><xsl:value-of select="$newline"/> + </extensions><xsl:value-of select="$newline"/> + </xsl:if> + </trkpt><xsl:value-of select="$newline"/> + </xsl:if> + </xsl:for-each> + <xsl:value-of select="$newline"/> + <extensions><xsl:value-of select="$newline"/> + <gpxdata:sportType><xsl:value-of select="$sport"/></gpxdata:sportType><xsl:value-of select="$newline"/> + <gpxdata:calories><xsl:value-of select="$calories"/></gpxdata:calories><xsl:value-of select="$newline"/> + </extensions><xsl:value-of select="$newline"/> + </trkseg><xsl:value-of select="$newline"/> + </xsl:for-each> + </trk><xsl:value-of select="$newline"/> + </gpx><xsl:value-of select="$newline"/> +</xsl:template> +</xsl:stylesheet> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-09-23 11:22:29
|
Revision: 355 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=355&view=rev Author: jblance Date: 2009-09-23 11:22:23 +0000 (Wed, 23 Sep 2009) Log Message: ----------- New TCX v2 import plugin Modified Paths: -------------- pytrainer/trunk/plugins/googleearth/conf.xml Added Paths: ----------- pytrainer/trunk/plugins/googleearth/garmin-tcxv2.py pytrainer/trunk/plugins/googleearth/garmin-tcxv2.pyc pytrainer/trunk/plugins/googleearth/translate.xsl Removed Paths: ------------- pytrainer/trunk/plugins/googleearth/main.sh Modified: pytrainer/trunk/plugins/googleearth/conf.xml =================================================================== --- pytrainer/trunk/plugins/googleearth/conf.xml 2009-09-23 11:20:37 UTC (rev 354) +++ pytrainer/trunk/plugins/googleearth/conf.xml 2009-09-23 11:22:23 UTC (rev 355) @@ -1,9 +1,9 @@ <?xml version="1.0" ?> <pytrainer-plugin - name="Google Earth" - description="Import yor Google Earth files (*.kml)" - plugincode="googleearth" - pluginbutton="Import Google Earth File (*.kml)" - executable="main.sh" + name="Garmin v2 TCX" + description="Import your records from a version 2 TCX file from a Garmin gps device (i.e. Forerunner 405)" + plugincode="garminTCXv2" + pluginbutton="Import from Garmin TCX (version 2)" + executable="garmin-tcxv2" > </pytrainer-plugin> Added: pytrainer/trunk/plugins/googleearth/garmin-tcxv2.py =================================================================== --- pytrainer/trunk/plugins/googleearth/garmin-tcxv2.py (rev 0) +++ pytrainer/trunk/plugins/googleearth/garmin-tcxv2.py 2009-09-23 11:22:23 UTC (rev 355) @@ -0,0 +1,57 @@ +# -*- coding: iso-8859-1 -*- + +#Copyright (C) Fiz Vazquez vu...@si... +# Modified by dgranda + +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either version 2 +#of the License, or (at your option) any later version. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. + +#You should have received a copy of the GNU General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import logging +import os +import libxml2 +import libxslt + +class garminTCXv2(): + def __init__(self, parent = None): + self.parent = parent + self.tmpdir = self.parent.conf.getValue("tmpdir") + + def run(self): + logging.debug(">>") + # able to select multiple files.... + f = os.popen("zenity --file-selection --multiple --title 'Choose a TCX file to import'") + inputData = f.read().strip() + inputfiles = inputData.split('|') + xslfile= os.path.dirname(os.path.realpath(__file__)) + "/translate.xsl" + outputfile=[] + if os.path.isfile(xslfile): + for index in range(len(inputfiles)): + outputfile.append(self.tmpdir+"/outputfile"+str(index)+".gpx") + inputfile=inputfiles[index] + if os.path.isfile(inputfile): + styledoc = libxml2.parseFile(xslfile) + style = libxslt.parseStylesheetDoc(styledoc) + doc = libxml2.parseFile(inputfile) + result = style.applyStylesheet(doc, None) + style.saveResultToFilename(outputfile[index], result, 0) + style.freeStylesheet() + doc.freeDoc() + result.freeDoc() + else: + raise Exception("XML input file not found, looking for: " + inputfile) + else: + raise Exception("XSL file not found, looking for: " + xslfile) + logging.debug("<<") + return outputfile + Added: pytrainer/trunk/plugins/googleearth/garmin-tcxv2.pyc =================================================================== (Binary files differ) Property changes on: pytrainer/trunk/plugins/googleearth/garmin-tcxv2.pyc ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Deleted: pytrainer/trunk/plugins/googleearth/main.sh =================================================================== --- pytrainer/trunk/plugins/googleearth/main.sh 2009-09-23 11:20:37 UTC (rev 354) +++ pytrainer/trunk/plugins/googleearth/main.sh 2009-09-23 11:22:23 UTC (rev 355) @@ -1,26 +0,0 @@ -#!/bin/sh -# -*- coding: iso-8859-1 -*- - -#Copyright (C) Fiz Vazquez vu...@si... - -#This program is free software; you can redistribute it and/or -#modify it under the terms of the GNU General Public License -#as published by the Free Software Foundation; either version 2 -#of the License, or (at your option) any later version. - -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. - -#You should have received a copy of the GNU General Public License -#along with this program; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - -var=`zenity --file-selection` - -tmpgpx="/tmp/reg.gpx" -gpsbabel -t -i kml -f $var -o gpx -F $tmpgpx - -echo $tmpgpx Added: pytrainer/trunk/plugins/googleearth/translate.xsl =================================================================== --- pytrainer/trunk/plugins/googleearth/translate.xsl (rev 0) +++ pytrainer/trunk/plugins/googleearth/translate.xsl 2009-09-23 11:22:23 UTC (rev 355) @@ -0,0 +1,63 @@ +<?xml version="1.0"?> + +<!-- note defining a namespace for TrainingCenterDatabase as the translation does not seem to work with a default namespace --> +<xsl:stylesheet version="1.0" +xmlns:t="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2" +xmlns:xsl="http://www.w3.org/1999/XSL/Transform" +> +<xsl:output method="xml" indent="yes" omit-xml-declaration="no"/> + +<!-- this is a bit of a messy way to get whitespace into the output - but it works --> +<xsl:variable name="newline"><xsl:text> +</xsl:text></xsl:variable> + +<xsl:template match="/"> + <gpx xmlns="http://www.topografix.com/GPX/1/1" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:gpxdata="http://www.cluetrust.com/XML/GPXDATA/1/0" + creator="pytrainer http://sourceforge.net/projects/pytrainer" version="1.1" + xsi:schemaLocation="http://www.topografix.com/GPX/1/1 + http://www.topografix.com/GPX/1/1/gpx.xsd + http://www.cluetrust.com/XML/GPXDATA/1/0 + http://www.cluetrust.com/Schemas/gpxdata10.xsd"> + + <xsl:value-of select="$newline"/> + <xsl:variable name="sport"><xsl:value-of select="t:TrainingCenterDatabase/t:Activities/t:Activity/@Sport"/></xsl:variable> + <xsl:variable name="time"><xsl:value-of select="t:TrainingCenterDatabase/t:Activities/t:Activity/t:Id"/></xsl:variable> + <xsl:variable name="name"><xsl:value-of select="$sport"/><xsl:value-of select="substring($time, 1,10)"/></xsl:variable> + <metadata><xsl:value-of select="$newline"/> + <name><xsl:value-of select="$name"/></name><xsl:value-of select="$newline"/> + <link href="http://sourceforge.net/projects/pytrainer"/><xsl:value-of select="$newline"/> + <time><xsl:value-of select="$time"/></time><xsl:value-of select="$newline"/> + </metadata><xsl:value-of select="$newline"/> + <trk><xsl:value-of select="$newline"/> + <xsl:for-each select="t:TrainingCenterDatabase/t:Activities/t:Activity/t:Lap"> + <trkseg><xsl:value-of select="$newline"/> + <xsl:variable name="calories"><xsl:value-of select="t:Calories"/></xsl:variable> + <xsl:for-each select="t:Track/t:Trackpoint"> + <!-- only output a trkpt if a position exists --> + <xsl:if test="t:Position"> + <xsl:variable name="lat"><xsl:value-of select="t:Position/t:LatitudeDegrees"/></xsl:variable> + <xsl:variable name="lon"><xsl:value-of select="t:Position/t:LongitudeDegrees"/></xsl:variable> + <trkpt lat="{$lat}" lon="{$lon}"><xsl:value-of select="$newline"/> + <ele><xsl:value-of select="t:AltitudeMeters"/></ele><xsl:value-of select="$newline"/> + <time><xsl:value-of select="t:Time"/></time><xsl:value-of select="$newline"/> + <xsl:if test="t:HeartRateBpm/t:Value"> + <extensions><xsl:value-of select="$newline"/> + <gpxdata:hr><xsl:value-of select="t:HeartRateBpm/t:Value"/></gpxdata:hr><xsl:value-of select="$newline"/> + </extensions><xsl:value-of select="$newline"/> + </xsl:if> + </trkpt><xsl:value-of select="$newline"/> + </xsl:if> + </xsl:for-each> + <xsl:value-of select="$newline"/> + <extensions><xsl:value-of select="$newline"/> + <gpxdata:sportType><xsl:value-of select="$sport"/></gpxdata:sportType><xsl:value-of select="$newline"/> + <gpxdata:calories><xsl:value-of select="$calories"/></gpxdata:calories><xsl:value-of select="$newline"/> + </extensions><xsl:value-of select="$newline"/> + </trkseg><xsl:value-of select="$newline"/> + </xsl:for-each> + </trk><xsl:value-of select="$newline"/> + </gpx><xsl:value-of select="$newline"/> +</xsl:template> +</xsl:stylesheet> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-09-23 11:20:46
|
Revision: 354 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=354&view=rev Author: jblance Date: 2009-09-23 11:20:37 +0000 (Wed, 23 Sep 2009) Log Message: ----------- Test plugin for Garmin Hr from a file Modified Paths: -------------- pytrainer/branches/plugins-v2/plugins/garmin-hr/conf.xml Added Paths: ----------- pytrainer/branches/plugins-v2/plugins/garmin-hr/garminhrfile.py Removed Paths: ------------- pytrainer/branches/plugins-v2/plugins/garmin-hr/main.py Modified: pytrainer/branches/plugins-v2/plugins/garmin-hr/conf.xml =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr/conf.xml 2009-09-23 11:15:01 UTC (rev 353) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr/conf.xml 2009-09-23 11:20:37 UTC (rev 354) @@ -1,10 +1,9 @@ <?xml version="1.0" ?> <pytrainer-plugin name="Garmin Heart Rate" - description="Import yor records direclty from your garmin gps device with heart rate support" - plugincode="garminhr" - pluginbutton="Import from Garmin (HR support)" - executable="main" + description="Import records from a garmin gps device with heart rate support (from a file)" + plugincode="garminhrfile" + pluginbutton="Import from Garmin file (HR support)" + executable="garminhrfile" > -<conf-values variable="device" value="usb:"/> </pytrainer-plugin> Added: pytrainer/branches/plugins-v2/plugins/garmin-hr/garminhrfile.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr/garminhrfile.py (rev 0) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr/garminhrfile.py 2009-09-23 11:20:37 UTC (rev 354) @@ -0,0 +1,86 @@ +#!/usr/bin/python +# -*- coding: iso-8859-1 -*- + +#Copyright (C) Fiz Vazquez vu...@si... + +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either version 2 +#of the License, or (at your option) any later version. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. + +#You should have received a copy of the GNU General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import os +import logging +import commands + +from lib.xmlUtils import XMLParser +from lib.gpx import Gpx + +class garminhrfile(): + def __init__(self, parent = None): + self.parent = parent + self.tmpdir = self.parent.conf.getValue("tmpdir") + + def run(self): + f = os.popen("zenity --file-selection --title 'Choose a Garmin Training Center file to import'") + gtrnctrFile = f.read().strip() + + # XML file from gpsbabel refers to schemas and namespace definitions which are no longer available, removing this info - dgg - 12.05.2008 + # check to see if we can remove this... + gtrnctrFileMod = removeHeaders(gtrnctrFile) + print "modified gtrnctrfile: " + gtrnctrFileMod + + return [gtrnctrFileMod,] #TODO this is where the conversion and checking will occur + + def removeHeaders(gtrnctrFile): + if os.path.isfile(gtrnctrFile): + gtrnctrFileMod = self.tmpdir+"/file_mod.gtrnctr" + f = open(gtrnctrFile,"r") + lines = f.readlines() + f.close() + f = open(gtrnctrFileMod,'w') + headers = lines[0]+'<TrainingCenterDatabase>\n' + f.write(headers) + f.write(''.join(lines[6:])) + f.close() + return gtrnctrFileMod + else: + return None + + def importFromGTRNCTR(self,gtrnctrFile): + """22.03.2008 - dgranda + Retrieves sport, date and start time from each entry coming from GPS + and compares with what is stored locally, just to import new entries + 31.08.2008 - dgranda - Only checks start time, discarding sport info + args: file with data from GPS file (garmin format) + returns: none""" + logging.debug('>>') + logging.info('Retrieving data from '+gtrnctrFile) + xmlParser=XMLParser(gtrnctrFile) + listTracksGPS = xmlParser.shortFromGPS(gtrnctrFile, True) + logging.info('GPS: '+str(len(listTracksGPS))+' entries found') + if len(listTracksGPS)>0: + listTracksLocal = self.shortFromLocalDB(True) + logging.info('Local: '+str(len(listTracksLocal))+' entries found') + listNewTracks=self.compareTracks(listTracksGPS,listTracksLocal,False) + newTracks = len(listNewTracks) + # empty constructor for Gpx + gpx = Gpx() + i=0 + for entry in listNewTracks: + i=i+1 + logging.debug('Entry summary to import: '+str(entry)) + newGPX=gpx.retrieveDataFromGTRNCTR(gtrnctrFile, entry) + entry_id = self.insertNewRecord(newGPX, entry) + logging.info('Entry '+str(entry_id)+' has been added ('+str(i)+'/'+str(newTracks)+')') + else: + logging.info('No tracks found in GPS device') + logging.debug('<<') Deleted: pytrainer/branches/plugins-v2/plugins/garmin-hr/main.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr/main.py 2009-09-23 11:15:01 UTC (rev 353) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr/main.py 2009-09-23 11:20:37 UTC (rev 354) @@ -1,69 +0,0 @@ -#!/usr/bin/python -# -*- coding: iso-8859-1 -*- - -#Copyright (C) Fiz Vazquez vu...@si... - -#This program is free software; you can redistribute it and/or -#modify it under the terms of the GNU General Public License -#as published by the Free Software Foundation; either version 2 -#of the License, or (at your option) any later version. - -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. - -#You should have received a copy of the GNU General Public License -#along with this program; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - -from optparse import OptionParser -#from gtrnctr2gpx import gtrnctr2gpx -import os -import commands - -class garminhr(): - def __init__(self, parent = None): - self.parent = parent - self.tmpdir = self.parent.conf.getValue("tmpdir") - - def run(self): - parser = OptionParser() - parser.add_option("-d", "--device", dest="device") - (options,args) = parser.parse_args() - gtrnctrFile="/tmp/file.gtrnctr" - gtrnctrFileMod="/tmp/file_mod.gtrnctr" - input_dev = options.device - - # ToDo (19.05.2008): better exception handling - try: - outmod = commands.getstatusoutput('/sbin/lsmod | grep garmin_gps') - #os.popen("zenity --error --text='Devuelve: %s'" %str(outmod)) - if outmod[0]==256: #there is no garmin_gps module loaded - input_dev = "usb:" - else: - raise Exception - # Can't export to GPX directly because lack of support for heartrate and sports (1.0 version, may change when gpsbabel supports 1.1 with custom fields) - outgps = commands.getstatusoutput("gpsbabel -t -i garmin -f %s -o gtrnctr -F /tmp/file.gtrnctr | zenity --progress --pulsate --text='Loading Data' auto-close" %input_dev) - #os.popen("zenity --error --text='Devuelve: %s'" %str(outgps)) - # XML file from gpsbabel refers to schemas and namespace definitions which are no longer available, removing this info - dgg - 12.05.2008 - if outgps[0]==0: - if outgps[1] == "Found no Garmin USB devices.": # check localizations - raise Exception - else: - if os.path.isfile(gtrnctrFile): - f = open(gtrnctrFile,"r") - lines = f.readlines() - f.close() - f = open(gtrnctrFileMod,'w') - headers = lines[0]+'<TrainingCenterDatabase>\n' - f.write(headers) - f.write(''.join(lines[6:])) - f.close() - return [gtrnctrFileMod,] #TODO this is where the conversion and checking will occur - else: - raise Exception - except Exception: - os.popen("zenity --error --text='Can not handle Garmin device\nCheck your configuration\nCurrent usb port is set to:\t %s'" %input_dev); - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-09-23 11:15:11
|
Revision: 353 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=353&view=rev Author: jblance Date: 2009-09-23 11:15:01 +0000 (Wed, 23 Sep 2009) Log Message: ----------- New additions for changes to plugins Added Paths: ----------- pytrainer/branches/plugins-v2/PLUGINS.README pytrainer/branches/plugins-v2/plugins/googleearth/main.py Removed Paths: ------------- pytrainer/branches/plugins-v2/plugins/garmin-hr/gtrnctr2gpx.py Added: pytrainer/branches/plugins-v2/PLUGINS.README =================================================================== --- pytrainer/branches/plugins-v2/PLUGINS.README (rev 0) +++ pytrainer/branches/plugins-v2/PLUGINS.README 2009-09-23 11:15:01 UTC (rev 353) @@ -0,0 +1,31 @@ +Information on creating Plugins +=========================================== + +Plugins are created by: +1) Making a directory in <pytrainer>/plugins/ +2) Creating a python class in a file in your directory + - class must have run(self) function + - run(self) returns tuple of GPX files to import +3) Creating a conf.xml configuration file in your directory with at least the following information: + <?xml version="1.0" ?> + <pytrainer-plugin + name="Garmin v2 TCX" + description="Import your records from a version 2 TCX file from a Garmin gps device (i.e. Forerunner 405)" + plugincode="garminTCXv2" + pluginbutton="Import from Garmin TCX (version 2)" + executable="garmintcxv2" + > + </pytrainer-plugin> + +Where + name: is the name of your plugin + description: is the description + plugincode: is the name of the class in your plugin file + pluginbutton: is the label that the menu option will have once your plugin is enabled + executable: is the file that the python class in in (without the .py extension) + + + + + + Deleted: pytrainer/branches/plugins-v2/plugins/garmin-hr/gtrnctr2gpx.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr/gtrnctr2gpx.py 2009-09-23 11:12:05 UTC (rev 352) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr/gtrnctr2gpx.py 2009-09-23 11:15:01 UTC (rev 353) @@ -1,82 +0,0 @@ -#!/usr/bin/python -# -*- coding: iso-8859-1 -*- - -#Copyright (C) Fiz Vazquez vu...@si... - -#This program is free software; you can redistribute it and/or -#modify it under the terms of the GNU General Public License -#as published by the Free Software Foundation; either version 2 -#of the License, or (at your option) any later version. - -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. - -#You should have received a copy of the GNU General Public License -#along with this program; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - -import sys - -import xml.dom.minidom - -#the _variables are the gpx ones. The variables are the xcsv one - - -def gtrnctr2gpx(gtrnctrfile,gpxfile): - dom = xml.dom.minidom.parse(gtrnctrfile) - d = xml.dom.minidom.getDOMImplementation() - _dom = d.createDocument(None,"gpx",None) - _gpx_element = _dom.documentElement - _gpx_element.setAttribute('creator',"pytrainer http://pytrainer.e-oss.net") - _gpx_element.setAttribute('version',"1.1") - _gpx_element.setAttribute('xmlns',"http://www.topografix.com/GPX/1/1") - _gpx_element.setAttribute('xmlns:geocache',"http://www.groundspeak.com/cache/1/0") - _gpx_element.setAttribute('xmlns:gpxdata',"http://www.cluetrust.com/XML/GPXDATA/1/0") - _gpx_element.setAttribute('xmlns:xsi',"http://www.w3.org/2001/XMLSchema-instance") - _gpx_element.setAttribute('xsi:schemaLocation',"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.cluetrust.com/XML/GPXDATA/1/0 http://www.cluetrust.com/Schemas/gpxdata10.xsd") - - trks = dom.getElementsByTagName("Track") - nametrack = 0 - for trk in trks: - nametrack = nametrack+1 - _trk = _dom.createElement("trk") - _name = _dom.createElement("name") - _name.appendChild(_dom.createTextNode("%s"%str(nametrack))) - _trk.appendChild(_name) - trkpoints = trk.getElementsByTagName("Trackpoint") - for trkpoint in trkpoints: - _trkpt = _dom.createElement("trkpt") - time = trkpoint.getElementsByTagName("Time")[0].firstChild.data - alt = trkpoint.getElementsByTagName("AltitudeMeters")[0].firstChild.data - if len(trkpoint.getElementsByTagName("HeartRateBpm"))>0: - hr = trkpoint.getElementsByTagName("HeartRateBpm")[0].firstChild.data - else: - hr = "0" - lat = trkpoint.getElementsByTagName("LatitudeDegrees")[0].firstChild.data - lon = trkpoint.getElementsByTagName("LongitudeDegrees")[0].firstChild.data - - _time = _dom.createElement("time") - _ele = _dom.createElement("ele") - _hr = _dom.createElement("gpxdata:hr") - _extensions = _dom.createElement("extensions") - _time.appendChild(_dom.createTextNode(time)) - _ele.appendChild(_dom.createTextNode(alt)) - _hr.appendChild(_dom.createTextNode(hr)) - _extensions.appendChild(_hr) - _trkpt.appendChild(_time) - _trkpt.appendChild(_ele) - _trkpt.appendChild(_extensions) - _trkpt.setAttribute('lat', lat) - _trkpt.setAttribute('lon', lon) - _trk.appendChild(_trkpt) - _gpx_element.appendChild(_trk) - - f = open(gpxfile, 'w') - #_dom.writexml(f) - #f.write(_dom.toprettyxml()) - f.write(_dom.toxml()) - f.close() - Added: pytrainer/branches/plugins-v2/plugins/googleearth/main.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/googleearth/main.py (rev 0) +++ pytrainer/branches/plugins-v2/plugins/googleearth/main.py 2009-09-23 11:15:01 UTC (rev 353) @@ -0,0 +1,37 @@ +#!/usr/bin/python +# -*- coding: iso-8859-1 -*- + +#Copyright (C) Fiz Vazquez vu...@si... + +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either version 2 +#of the License, or (at your option) any later version. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. + +#You should have received a copy of the GNU General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +import os +import commands + +class googleearth(): + def __init__(self, parent = None): + self.parent = parent + self.tmpdir = self.parent.conf.getValue("tmpdir") + + def run(self): + f = os.popen("zenity --file-selection --title 'Choose a Google Earth file (.kml) to import'") + inputData = f.read().strip() + + tmpgpx="/tmp/reg.gpx" + outgps = commands.getstatusoutput("gpsbabel -t -i kml -f %s -o gpx -F %s" % (inputData, tmpgpx) ) + + return [tmpgpx, ] + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-09-23 11:12:12
|
Revision: 352 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=352&view=rev Author: jblance Date: 2009-09-23 11:12:05 +0000 (Wed, 23 Sep 2009) Log Message: ----------- Removing debug changes Modified Paths: -------------- pytrainer/branches/plugins-v2/pytrainer.sh Modified: pytrainer/branches/plugins-v2/pytrainer.sh =================================================================== --- pytrainer/branches/plugins-v2/pytrainer.sh 2009-09-23 11:10:19 UTC (rev 351) +++ pytrainer/branches/plugins-v2/pytrainer.sh 2009-09-23 11:12:05 UTC (rev 352) @@ -6,5 +6,4 @@ PATH_XULRUNNER=/usr/lib XULRUNNER_VERSION=`ls "$PATH_XULRUNNER" | grep xulrunner` export MOZILLA_FIVE_HOME=$PATH_XULRUNNER/$XULRUNNER_VERSION -rm /home/johnb/.pytrainer/log.out -python pytrainer.py -d +python pytrainer.py $1 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-09-23 11:10:27
|
Revision: 351 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=351&view=rev Author: jblance Date: 2009-09-23 11:10:19 +0000 (Wed, 23 Sep 2009) Log Message: ----------- Interim updates/changes to plugins - GPX and TCXv2 working so far... Modified Paths: -------------- pytrainer/branches/plugins-v2/plugins/garmin-hr/conf.xml pytrainer/branches/plugins-v2/plugins/garmin-hr/main.py pytrainer/branches/plugins-v2/plugins/garmingpx/conf.xml pytrainer/branches/plugins-v2/plugins/garmingpx/main.py pytrainer/branches/plugins-v2/plugins/googleearth/conf.xml pytrainer/branches/plugins-v2/pytrainer/main.py pytrainer/branches/plugins-v2/pytrainer/plugins.py pytrainer/branches/plugins-v2/pytrainer/record.py pytrainer/branches/plugins-v2/pytrainer.sh Removed Paths: ------------- pytrainer/branches/plugins-v2/plugins/ipod/ Modified: pytrainer/branches/plugins-v2/plugins/garmin-hr/conf.xml =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr/conf.xml 2009-09-23 10:13:16 UTC (rev 350) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr/conf.xml 2009-09-23 11:10:19 UTC (rev 351) @@ -2,9 +2,9 @@ <pytrainer-plugin name="Garmin Heart Rate" description="Import yor records direclty from your garmin gps device with heart rate support" - plugincode="garmin-hr" + plugincode="garminhr" pluginbutton="Import from Garmin (HR support)" - executable="main.py" + executable="main" > <conf-values variable="device" value="usb:"/> </pytrainer-plugin> Modified: pytrainer/branches/plugins-v2/plugins/garmin-hr/main.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmin-hr/main.py 2009-09-23 10:13:16 UTC (rev 350) +++ pytrainer/branches/plugins-v2/plugins/garmin-hr/main.py 2009-09-23 11:10:19 UTC (rev 351) @@ -23,41 +23,47 @@ import os import commands -parser = OptionParser() -parser.add_option("-d", "--device", dest="device") -(options,args) = parser.parse_args() -gtrnctrFile="/tmp/file.gtrnctr" -gtrnctrFileMod="/tmp/file_mod.gtrnctr" -input_dev = options.device +class garminhr(): + def __init__(self, parent = None): + self.parent = parent + self.tmpdir = self.parent.conf.getValue("tmpdir") -# ToDo (19.05.2008): better exception handling -try: - outmod = commands.getstatusoutput('/sbin/lsmod | grep garmin_gps') - #os.popen("zenity --error --text='Devuelve: %s'" %str(outmod)) - if outmod[0]==256: #there is no garmin_gps module loaded - input_dev = "usb:" - else: - raise Exception - # Can't export to GPX directly because lack of support for heartrate and sports (1.0 version, may change when gpsbabel supports 1.1 with custom fields) - outgps = commands.getstatusoutput("gpsbabel -t -i garmin -f %s -o gtrnctr -F /tmp/file.gtrnctr | zenity --progress --pulsate --text='Loading Data' auto-close" %input_dev) - #os.popen("zenity --error --text='Devuelve: %s'" %str(outgps)) - # XML file from gpsbabel refers to schemas and namespace definitions which are no longer available, removing this info - dgg - 12.05.2008 - if outgps[0]==0: - if outgps[1] == "Found no Garmin USB devices.": # check localizations - raise Exception - else: - if os.path.isfile(gtrnctrFile): - f = open(gtrnctrFile,"r") - lines = f.readlines() - f.close() - f = open(gtrnctrFileMod,'w') - headers = lines[0]+'<TrainingCenterDatabase>\n' - f.write(headers) - f.write(''.join(lines[6:])) - f.close() - print gtrnctrFileMod - else: - raise Exception -except Exception: - os.popen("zenity --error --text='Can not handle Garmin device\nCheck your configuration\nCurrent usb port is set to:\t %s'" %input_dev); + def run(self): + parser = OptionParser() + parser.add_option("-d", "--device", dest="device") + (options,args) = parser.parse_args() + gtrnctrFile="/tmp/file.gtrnctr" + gtrnctrFileMod="/tmp/file_mod.gtrnctr" + input_dev = options.device + # ToDo (19.05.2008): better exception handling + try: + outmod = commands.getstatusoutput('/sbin/lsmod | grep garmin_gps') + #os.popen("zenity --error --text='Devuelve: %s'" %str(outmod)) + if outmod[0]==256: #there is no garmin_gps module loaded + input_dev = "usb:" + else: + raise Exception + # Can't export to GPX directly because lack of support for heartrate and sports (1.0 version, may change when gpsbabel supports 1.1 with custom fields) + outgps = commands.getstatusoutput("gpsbabel -t -i garmin -f %s -o gtrnctr -F /tmp/file.gtrnctr | zenity --progress --pulsate --text='Loading Data' auto-close" %input_dev) + #os.popen("zenity --error --text='Devuelve: %s'" %str(outgps)) + # XML file from gpsbabel refers to schemas and namespace definitions which are no longer available, removing this info - dgg - 12.05.2008 + if outgps[0]==0: + if outgps[1] == "Found no Garmin USB devices.": # check localizations + raise Exception + else: + if os.path.isfile(gtrnctrFile): + f = open(gtrnctrFile,"r") + lines = f.readlines() + f.close() + f = open(gtrnctrFileMod,'w') + headers = lines[0]+'<TrainingCenterDatabase>\n' + f.write(headers) + f.write(''.join(lines[6:])) + f.close() + return [gtrnctrFileMod,] #TODO this is where the conversion and checking will occur + else: + raise Exception + except Exception: + os.popen("zenity --error --text='Can not handle Garmin device\nCheck your configuration\nCurrent usb port is set to:\t %s'" %input_dev); + Modified: pytrainer/branches/plugins-v2/plugins/garmingpx/conf.xml =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmingpx/conf.xml 2009-09-23 10:13:16 UTC (rev 350) +++ pytrainer/branches/plugins-v2/plugins/garmingpx/conf.xml 2009-09-23 11:10:19 UTC (rev 351) @@ -4,7 +4,7 @@ description="Import your records directly from a garmin gpx file." plugincode="garmingpx" pluginbutton="Import from Garmin GPX file" - executable="main.py" + executable="main" > <!--<conf-values variable="device" value="/dev/ttyUSB0"/>--> </pytrainer-plugin> Modified: pytrainer/branches/plugins-v2/plugins/garmingpx/main.py =================================================================== --- pytrainer/branches/plugins-v2/plugins/garmingpx/main.py 2009-09-23 10:13:16 UTC (rev 350) +++ pytrainer/branches/plugins-v2/plugins/garmingpx/main.py 2009-09-23 11:10:19 UTC (rev 351) @@ -18,14 +18,20 @@ import os -# Kind of lame to shell out for this.... -f = os.popen("zenity --file-selection --title 'Choose a GPX file to import'") +class garmingpx(): + def __init__(self, parent = None): + self.parent = parent + self.tmpdir = self.parent.conf.getValue("tmpdir") -file_name = f.read().strip() + def run(self): + # Kind of lame to shell out for this.... + f = os.popen("zenity --file-selection --multiple --title 'Choose a GPX file to import'") + inputData = f.read().strip() + inputfiles = inputData.split('|') -rv = f.close() -if rv: - if os.WEXITSTATUS(rv) != 0: - raise Exception() + rv = f.close() + if rv: + if os.WEXITSTATUS(rv) != 0: + raise Exception() -print file_name + return inputfiles Modified: pytrainer/branches/plugins-v2/plugins/googleearth/conf.xml =================================================================== --- pytrainer/branches/plugins-v2/plugins/googleearth/conf.xml 2009-09-23 10:13:16 UTC (rev 350) +++ pytrainer/branches/plugins-v2/plugins/googleearth/conf.xml 2009-09-23 11:10:19 UTC (rev 351) @@ -4,6 +4,6 @@ description="Import yor Google Earth files (*.kml)" plugincode="googleearth" pluginbutton="Import Google Earth File (*.kml)" - executable="main.sh" + executable="main" > </pytrainer-plugin> Modified: pytrainer/branches/plugins-v2/pytrainer/main.py =================================================================== --- pytrainer/branches/plugins-v2/pytrainer/main.py 2009-09-23 10:13:16 UTC (rev 350) +++ pytrainer/branches/plugins-v2/pytrainer/main.py 2009-09-23 11:10:19 UTC (rev 351) @@ -160,12 +160,16 @@ def runPlugin(self,widget,pathPlugin): logging.debug('>>') - gtrnctrFile = self.plugins.runPlugin(pathPlugin) - if os.path.isfile(gtrnctrFile): - logging.info('File exists. Size: '+ str(os.path.getsize(gtrnctrFile))) - self.record.importFromGTRNCTR(gtrnctrFile) - else: - logging.error('File '+gtrnctrFile+' not valid') + self.pluginClass = self.plugins.importClass(pathPlugin) + pluginFiles = self.pluginClass.run() + logging.debug("Plugin returned " +str(len(pluginFiles)) + " files: " +','.join(pluginFiles) ) + #process returned GPX files + for pluginFile in pluginFiles: + if os.path.isfile(pluginFile): + logging.info('File exists. Size: '+ str(os.path.getsize(pluginFile))) + self.record.importFromGPX(pluginFile) + else: + logging.error('File '+pluginFile+' not valid') logging.debug('<<') def runExtension(self,extension,id): Modified: pytrainer/branches/plugins-v2/pytrainer/plugins.py =================================================================== --- pytrainer/branches/plugins-v2/pytrainer/plugins.py 2009-09-23 10:13:16 UTC (rev 350) +++ pytrainer/branches/plugins-v2/pytrainer/plugins.py 2009-09-23 11:10:19 UTC (rev 351) @@ -17,6 +17,7 @@ #Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. import os +import sys import logging from lib.xmlUtils import XMLParser @@ -44,10 +45,28 @@ logging.info('Loading plugin '+name) logging.debug('<<') return button,plugin - - def runPlugin(self,pathPlugin): + + def importClass(self, pathPlugin): logging.debug('>>') info = XMLParser(pathPlugin+"/conf.xml") + #import plugin + plugin_dir = os.path.realpath(pathPlugin) + plugin_filename = info.getValue("pytrainer-plugin","executable") + plugin_classname = info.getValue("pytrainer-plugin","plugincode") + logging.debug("Plugin Filename: " + plugin_filename ) + logging.debug("Plugin Classname: " + plugin_classname) + sys.path.insert(0, plugin_dir) + module = __import__(plugin_filename) + logging.debug('<<') + pluginMain = getattr(module, plugin_classname) + return pluginMain(self) + + + + #def runPlugin(self,pathPlugin): + """ + logging.debug('>>') + info = XMLParser(pathPlugin+"/conf.xml") bin = info.getValue("pytrainer-plugin","executable") binary = pathPlugin+"/"+bin params = "" @@ -61,8 +80,9 @@ logging.debug('<<') if gpxfile == "0": return False - return gpxfile - + return gpxfile""" + + def managePlugins(self): pluginsList = self.getPluginsList() windowplugins = WindowPlugins(self.data_path, self) @@ -118,7 +138,8 @@ if not os.path.isdir(plugindir): os.mkdir(plugindir) if not os.path.isfile(plugindir+"/conf.xml"): - savedOptions.append(("status","0")) + if ("status", "1") not in savedOptions: + savedOptions.append(("status","0")) info = XMLParser(plugindir+"/conf.xml") info.createXMLFile("pytrainer-plugin",savedOptions) Modified: pytrainer/branches/plugins-v2/pytrainer/record.py =================================================================== --- pytrainer/branches/plugins-v2/pytrainer/record.py 2009-09-23 10:13:16 UTC (rev 350) +++ pytrainer/branches/plugins-v2/pytrainer/record.py 2009-09-23 11:10:19 UTC (rev 351) @@ -413,13 +413,14 @@ logging.info('Entry '+str(entry_id)+' has been added') logging.debug('<<') - def importFromGTRNCTR(self,gtrnctrFile): + #def importFromGTRNCTR(self,gtrnctrFile): """22.03.2008 - dgranda Retrieves sport, date and start time from each entry coming from GPS and compares with what is stored locally, just to import new entries 31.08.2008 - dgranda - Only checks start time, discarding sport info args: file with data from GPS file (garmin format) returns: none""" + """ logging.debug('>>') logging.info('Retrieving data from '+gtrnctrFile) xmlParser=XMLParser(gtrnctrFile) @@ -442,6 +443,7 @@ else: logging.info('No tracks found in GPS device') logging.debug('<<') + """ def shortFromLocal(self): """25.03.2008 - dgranda Modified: pytrainer/branches/plugins-v2/pytrainer.sh =================================================================== --- pytrainer/branches/plugins-v2/pytrainer.sh 2009-09-23 10:13:16 UTC (rev 350) +++ pytrainer/branches/plugins-v2/pytrainer.sh 2009-09-23 11:10:19 UTC (rev 351) @@ -6,4 +6,5 @@ PATH_XULRUNNER=/usr/lib XULRUNNER_VERSION=`ls "$PATH_XULRUNNER" | grep xulrunner` export MOZILLA_FIVE_HOME=$PATH_XULRUNNER/$XULRUNNER_VERSION -python pytrainer.py $1 +rm /home/johnb/.pytrainer/log.out +python pytrainer.py -d This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-09-23 10:13:34
|
Revision: 350 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=350&view=rev Author: jblance Date: 2009-09-23 10:13:16 +0000 (Wed, 23 Sep 2009) Log Message: ----------- Fix to allow plugins to be enabled first attempt Modified Paths: -------------- pytrainer/trunk/pytrainer/plugins.py Modified: pytrainer/trunk/pytrainer/plugins.py =================================================================== --- pytrainer/trunk/pytrainer/plugins.py 2009-09-23 09:15:18 UTC (rev 349) +++ pytrainer/trunk/pytrainer/plugins.py 2009-09-23 10:13:16 UTC (rev 350) @@ -118,7 +118,8 @@ if not os.path.isdir(plugindir): os.mkdir(plugindir) if not os.path.isfile(plugindir+"/conf.xml"): - savedOptions.append(("status","0")) + if ("status", "1") not in savedOptions: + savedOptions.append(("status","0")) info = XMLParser(plugindir+"/conf.xml") info.createXMLFile("pytrainer-plugin",savedOptions) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-09-23 09:15:29
|
Revision: 349 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=349&view=rev Author: jblance Date: 2009-09-23 09:15:18 +0000 (Wed, 23 Sep 2009) Log Message: ----------- Changes to allow sport addition on the fly, added importFromGPX function Modified Paths: -------------- pytrainer/branches/plugins-v2/pytrainer/record.py Modified: pytrainer/branches/plugins-v2/pytrainer/record.py =================================================================== --- pytrainer/branches/plugins-v2/pytrainer/record.py 2009-09-23 06:49:49 UTC (rev 348) +++ pytrainer/branches/plugins-v2/pytrainer/record.py 2009-09-23 09:15:18 UTC (rev 349) @@ -121,7 +121,7 @@ list_options["rcd_beats"] = 0 #retrieving sport id (adding sport if it doesn't exist yet) - sport_id = self.getSportId(list_options["rcd_sport"],add=None) + sport_id = self.getSportId(list_options["rcd_sport"],add=True) values= ( list_options["rcd_date"], @@ -276,12 +276,12 @@ sport_id = self.ddbb.select("sports","id_sports","name=\"%s\"" %(sport))[0][0] except: logging.error('Error retrieving id_sports from '+ str(sport)) - traceback.print_last() + #traceback.print_last() if add is None: logging.debug('Sport '+str(sport)+' will not be added to DB') else: logging.debug('Adding sport '+str(sport)+' to DB') - sport_id = self.addNewSport(self,sport,0,0) + sport_id = self.addNewSport(sport,"0","0") logging.debug('<<') return sport_id @@ -295,8 +295,8 @@ returns: id_sports from new sport""" logging.debug(">>") logging.debug("Adding new sport: "+sport+"|"+weight+"|"+met) - sport = [sport,met,weight] - self.ddbb.insert("sports","name,met,weight",sport) + sportT = [sport,met,weight] + self.ddbb.insert("sports","name,met,weight",sportT) sport_id = self.ddbb.select("sports","id_sports","name=\"%s\"" %(sport))[0][0] logging.debug("<<") return sport_id @@ -401,6 +401,18 @@ self.recordwindow.run() logging.debug('<<') + def importFromGPX(self, gpxFile): + """ + Add a record from a valid pytrainer type GPX file + """ + logging.debug('>>') + logging.info('Retrieving data from '+gpxFile) + #create an entry, defaulting sport to 'import' - in future could get actual sport from gpxFile.... + entry = ["import",""] + entry_id = self.insertNewRecord(gpxFile, entry) + logging.info('Entry '+str(entry_id)+' has been added') + logging.debug('<<') + def importFromGTRNCTR(self,gtrnctrFile): """22.03.2008 - dgranda Retrieves sport, date and start time from each entry coming from GPS This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-09-23 06:50:01
|
Revision: 348 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=348&view=rev Author: jblance Date: 2009-09-23 06:49:49 +0000 (Wed, 23 Sep 2009) Log Message: ----------- Merge 1.6.0.9 changes to plugins-v2 branch Modified Paths: -------------- pytrainer/branches/plugins-v2/CHANGES pytrainer/branches/plugins-v2/pytrainer/main.py Property Changed: ---------------- pytrainer/branches/plugins-v2/ Property changes on: pytrainer/branches/plugins-v2 ___________________________________________________________________ Added: svn:mergeinfo + /pytrainer/trunk:345-347 Modified: pytrainer/branches/plugins-v2/CHANGES =================================================================== --- pytrainer/branches/plugins-v2/CHANGES 2009-09-22 16:35:56 UTC (rev 347) +++ pytrainer/branches/plugins-v2/CHANGES 2009-09-23 06:49:49 UTC (rev 348) @@ -1,3 +1,14 @@ +- PyTrainer tasks for 1.6.0.9: + +Added dynamic loading and unloading of plugin menu items (svn rev 344) +Removal of decommissioned plugin (garmin301) and addition of new ones (garmingpx). Update of project data (version and url) (svn rev 343) +Adding calories support suggested by JB (svn rev 342) +Maximum is misspelled Maximun, see http://bugs.debian.org/537723 (svn 341) +Fixed some hardcoded stuff that prevents pytrainer to copy entries to ~/.pytrainer/gpx (thanks to JB) (svn 340) +Major improvements in graphs (thanks to Fiz) (svn revs 339, 336, 332, 331) +Updated german translation - bug ID: 2811507 (thanks to Noèl) (svn revs 338, 333) +Minor project and license information updated (svn revs 337, 335, 334, 329) + - PyTrainer tasks for 1.6.0.8: Rotating log file support added (rev 322, http://sourceforge.net/tracker/?func=detail&aid=2717142&group_id=213157&atid=1024595) Modified: pytrainer/branches/plugins-v2/pytrainer/main.py =================================================================== --- pytrainer/branches/plugins-v2/pytrainer/main.py 2009-09-22 16:35:56 UTC (rev 347) +++ pytrainer/branches/plugins-v2/pytrainer/main.py 2009-09-23 06:49:49 UTC (rev 348) @@ -86,7 +86,7 @@ def __init__(self,filename = None, data_path = None): logging.debug('>>') self.data_path = data_path - self.version ="1.6.0.8" # 19.04.2009 + self.version ="1.6.0.9" # 22.10.2009 self.date = Date() # Checking profile This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dg...@us...> - 2009-09-22 16:36:07
|
Revision: 347 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=347&view=rev Author: dgranda Date: 2009-09-22 16:35:56 +0000 (Tue, 22 Sep 2009) Log Message: ----------- Tagging 1.6.0.9 release Added Paths: ----------- pytrainer/tags/1.6.0.9/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dg...@us...> - 2009-09-22 16:21:46
|
Revision: 346 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=346&view=rev Author: dgranda Date: 2009-09-22 16:20:15 +0000 (Tue, 22 Sep 2009) Log Message: ----------- Setting version to 1.6.0.9 and publishing correspondent changelog Modified Paths: -------------- pytrainer/trunk/CHANGES pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/CHANGES =================================================================== --- pytrainer/trunk/CHANGES 2009-09-08 07:28:14 UTC (rev 345) +++ pytrainer/trunk/CHANGES 2009-09-22 16:20:15 UTC (rev 346) @@ -1,3 +1,14 @@ +- PyTrainer tasks for 1.6.0.9: + +Added dynamic loading and unloading of plugin menu items (svn rev 344) +Removal of decommissioned plugin (garmin301) and addition of new ones (garmingpx). Update of project data (version and url) (svn rev 343) +Adding calories support suggested by JB (svn rev 342) +Maximum is misspelled Maximun, see http://bugs.debian.org/537723 (svn 341) +Fixed some hardcoded stuff that prevents pytrainer to copy entries to ~/.pytrainer/gpx (thanks to JB) (svn 340) +Major improvements in graphs (thanks to Fiz) (svn revs 339, 336, 332, 331) +Updated german translation - bug ID: 2811507 (thanks to Noèl) (svn revs 338, 333) +Minor project and license information updated (svn revs 337, 335, 334, 329) + - PyTrainer tasks for 1.6.0.8: Rotating log file support added (rev 322, http://sourceforge.net/tracker/?func=detail&aid=2717142&group_id=213157&atid=1024595) Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2009-09-08 07:28:14 UTC (rev 345) +++ pytrainer/trunk/pytrainer/main.py 2009-09-22 16:20:15 UTC (rev 346) @@ -86,7 +86,7 @@ def __init__(self,filename = None, data_path = None): logging.debug('>>') self.data_path = data_path - self.version ="1.6.0.8" # 19.04.2009 + self.version ="1.6.0.9" # 22.10.2009 self.date = Date() # Checking profile This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-09-08 07:28:24
|
Revision: 345 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=345&view=rev Author: jblance Date: 2009-09-08 07:28:14 +0000 (Tue, 08 Sep 2009) Log Message: ----------- Branch to investigate changing the plugin design / approach Added Paths: ----------- pytrainer/branches/plugins-v2/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2009-08-08 10:48:39
|
Revision: 344 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=344&view=rev Author: jblance Date: 2009-08-08 10:48:27 +0000 (Sat, 08 Aug 2009) Log Message: ----------- Added dynamic loading and unloading of plugin menu items Modified Paths: -------------- pytrainer/trunk/pytrainer/gui/windowmain.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/pytrainer/gui/windowmain.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowmain.py 2009-08-03 17:39:15 UTC (rev 343) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2009-08-08 10:48:27 UTC (rev 344) @@ -80,8 +80,14 @@ savedOptions.append(("calories","False")) menufile.createXMLFile("listviewmenu",savedOptions) + def removeImportPlugin(self, plugin): + for widget in self.menuitem1_menu: + if widget.get_name() == plugin[1]: + self.menuitem1_menu.remove(widget) + def addImportPlugin(self,plugin): button = gtk.MenuItem(plugin[0]) + button.set_name(plugin[1]) button.connect("activate", self.parent.runPlugin, plugin[1]) self.menuitem1_menu.insert(button,2) self.menuitem1_menu.show_all() Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2009-08-03 17:39:15 UTC (rev 343) +++ pytrainer/trunk/pytrainer/main.py 2009-08-08 10:48:27 UTC (rev 344) @@ -305,7 +305,21 @@ def editGpsPlugins(self): logging.debug('>>') + activeplugins_before = self.plugins.getActivePlugins() self.plugins.managePlugins() + activeplugins_after = self.plugins.getActivePlugins() + #Need to check for plugins that have been disabled (were active and now are not) + for plugin in activeplugins_before: + if plugin not in activeplugins_after: + #disabled plugin -> need to unload plugin + txtbutton = self.plugins.loadPlugin(plugin) + self.windowmain.removeImportPlugin(txtbutton) + #Need to check for plugins that have been enabled (were not active and now are) + for plugin in activeplugins_after: + if plugin not in activeplugins_before: + #new active plugin -> need to load plugin + txtbutton = self.plugins.loadPlugin(plugin) + self.windowmain.addImportPlugin(txtbutton) logging.debug('<<') def newRecord(self,title=None,distance=None,time=None,upositive=None,unegative=None,bpm=None,calories=None,date=None,comment=None): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |