static PyObject* get_info(PyObject* obj, PyObject* args) { garmin_unit garmin; if (!initialize_garmin(&garmin)) return NULL; PyObject* dict = PyDict_New(); uint32 unit_id = garmin.id; PyDict_SetItem(dict, PyString_FromString("unit_id"), PyLong_FromUnsignedLong(unit_id)); uint16 product_id = garmin.product.product_id; PyDict_SetItem(dict, PyString_FromString("product_id"), PyInt_FromLong(product_id)); double software_version = garmin.product.software_version / 100.0; PyDict_SetItem(dict, PyString_FromString("software_version"), PyFloat_FromDouble(software_version)); char* product_description = garmin.product.product_description; PyDict_SetItem(dict, PyString_FromString("description"), PyString_FromString(product_description)); garmin_close(&garmin); return Py_BuildValue("N", dict); }
bool Edge305Device::isDeviceAvailable() { garmin_unit garmin; if ( garmin_init(&garmin,0) != 0 ) { garmin_close(&garmin); return true; } return false; }
TcxBase * Edge305Device::readFitnessDataFromGarmin() { TcxBase * fitData = NULL; garmin_unit garmin; garmin_data * data0; garmin_data * data1; garmin_data * data2; garmin_list * runs = NULL; garmin_list * laps = NULL; garmin_list * tracks = NULL; if ( garmin_init(&garmin,0) != 0 ) { Log::dbg("Extracting data from Garmin "+this->displayName); garmin_data * fitnessdata = garmin_get(&garmin,GET_RUNS); //garmin_data * fitnessdata = garmin_load("/workout/2010/02/20100227T152346.gmn"); //Testing only if (fitnessdata != NULL ) { Log::dbg("Received data from Garmin, processing data..."); fitData = new TcxBase(); // Add author information TcxAuthor * author = new TcxAuthor(); *(fitData)<<author; data0 = garmin_list_data(fitnessdata,0); data1 = garmin_list_data(fitnessdata,1); data2 = garmin_list_data(fitnessdata,2); if ( data0 != NULL && (data0->data != NULL) && data1 != NULL && (laps = (garmin_list*)data1->data) != NULL && data2 != NULL && (tracks = (garmin_list*)data2->data) != NULL ) { if (data0->type == data_Dlist) { runs = (garmin_list*)(data0->data); } else { runs = garmin_list_append(NULL,data0); } *(fitData) << printActivities(runs, laps, tracks, garmin); if (data0->type != data_Dlist) { garmin_free_list_only(runs); } Log::dbg("Done processing data..."); } else { Log::err("Some of the data read from the device was null (runs/laps/tracks)"); } } else { Log::err("Unable to extract any data!"); } garmin_free_data(fitnessdata); garmin_close(&garmin); } else { Log::err("Unable to open garmin device. Is it connected?"); } return fitData; }
/*static*/ string Edge305Device::getAttachedDeviceName() { garmin_unit garmin; string deviceName = ""; Log::dbg("Searching for garmin devices like Edge 305/Forerunner 305..."); if ( garmin_init(&garmin,0) != 0 ) { if (garmin.product.product_description != NULL) // Vista HCx also gets detected by this, but returns NULL values { deviceName = filterDeviceName((string)((char*)garmin.product.product_description)); Log::dbg("Found garmin device: "+deviceName); } garmin_close(&garmin); } return deviceName; }
string Edge305Device::getDeviceDescription() const { if (Log::enabledDbg()) Log::dbg("GpsDevice::getDeviceDescription() "+this->displayName); /* <?xml version="1.0" encoding="UTF-8" standalone="no" ?> <Device xmlns="http://www.garmin.com/xmlschemas/GarminDevice/v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.garmin.com/xmlschemas/GarminDevice/v2 http://www.garmin.com/xmlschemas/GarminDevicev2.xsd"> <Model> <PartNumber>006-B0450-00</PartNumber> <SoftwareVersion>320</SoftwareVersion> <Description>EDGE305 Software Version 3.20</Description> </Model> <Id>3305091776</Id> <DisplayName>Your name</DisplayName> <MassStorageMode> <DataType> <Name>GPSData</Name> <File> <Specification> <Identifier>http://www.topografix.com/GPX/1/1</Identifier> <Documentation>http://www.topografix.com/GPX/1/1/gpx.xsd</Documentation> </Specification> <Location> <FileExtension>GPX</FileExtension> </Location> <TransferDirection>InputOutput</TransferDirection> </File> </DataType> <DataType> <Name>FitnessHistory</Name> <File> <Specification> <Identifier>http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2</Identifier> <Documentation>http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd</Documentation> </Specification> <Location> <FileExtension>TCX</FileExtension> </Location> <TransferDirection>OutputFromUnit</TransferDirection> </File> </DataType> <DataType> <Name>FitnessUserProfile</Name> <File> <Specification> <Identifier>http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2</Identifier> <Documentation>http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd</Documentation> </Specification> <Location> <BaseName>UserProfile</BaseName> <FileExtension>TCX</FileExtension> </Location> <TransferDirection>InputOutput</TransferDirection> </File> </DataType> <DataType> <Name>FitnessCourses</Name> <File> <Specification> <Identifier>http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2</Identifier> <Documentation>http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd</Documentation> </Specification> <Location> <FileExtension>TCX</FileExtension> </Location> <TransferDirection>InputOutput</TransferDirection> </File> </DataType> <DataType> <Name>FitnessWorkouts</Name> <File> <Specification> <Identifier>http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2</Identifier> <Documentation>http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd</Documentation> </Specification> <Location> <FileExtension>TCX</FileExtension> </Location> <TransferDirection>InputOutput</TransferDirection> </File> </DataType> <UpdateFile> <PartNumber>006-B0450-00</PartNumber> <Version> <Major>0</Major> <Minor>0</Minor> </Version> <Description>Missing</Description> </UpdateFile> <UpdateFile> <PartNumber>006-B0478-00</PartNumber> <Version> <Major>0</Major> <Minor>0</Minor> </Version> <Description>Missing</Description> </UpdateFile> </MassStorageMode> <GarminMode> <Protocols> <Application Id="918"> <DataType>918</DataType> </Application> </Protocols> <Extensions> <GarminModeExtension xmlns="http://www.garmin.com/xmlschemas/GarminDeviceExtensions/v3"> <MemoryRegion> <Id>5</Id> <Version> <Major>0</Major> <Minor>0</Minor> </Version> <Description>Missing</Description> <ExpectedPartNumber>006-B0450-00</ExpectedPartNumber> <CurrentPartNumber>006-B0450-00</CurrentPartNumber> <IsErased>true</IsErased> <IsUserUpdateable>true</IsUserUpdateable> </MemoryRegion> <MemoryRegion> <Id>14</Id> <Version> <Major>3</Major> <Minor>20</Minor> </Version> <Description>EDGE305</Description> <ExpectedPartNumber>006-B0450-00</ExpectedPartNumber> <CurrentPartNumber>006-B0450-00</CurrentPartNumber> <IsUserUpdateable>true</IsUserUpdateable> </MemoryRegion> <MemoryRegion> <Id>246</Id> <Version> <Major>0</Major> <Minor>0</Minor> </Version> <Description>Missing</Description> <ExpectedPartNumber>006-B0478-00</ExpectedPartNumber> <CurrentPartNumber>006-B0478-00</CurrentPartNumber> <IsErased>true</IsErased> <IsUserUpdateable>true</IsUserUpdateable> </MemoryRegion> </GarminModeExtension> </Extensions> </GarminMode> </Device> */ garmin_unit garmin; if ( garmin_init(&garmin,0) != 0 ) { garmin_close(&garmin); } else { Log::err("Opening of garmin device failed. No longer attached!?"); return ""; } TiXmlDocument doc; TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "UTF-8", "no" ); doc.LinkEndChild( decl ); /*<Device xmlns="http://www.garmin.com/xmlschemas/GarminDevice/v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.garmin.com/xmlschemas/GarminDevice/v2 http://www.garmin.com/xmlschemas/GarminDevicev2.xsd">*/ TiXmlElement * device = new TiXmlElement( "Device" ); device->SetAttribute("xmlns", "http://www.garmin.com/xmlschemas/GarminDevice/v2"); device->SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); device->SetAttribute("xsi:schemaLocation", "http://www.garmin.com/xmlschemas/GarminDevice/v2 http://www.garmin.com/xmlschemas/GarminDevicev2.xsd"); doc.LinkEndChild( device ); /*<Model> <PartNumber>006-B0450-00</PartNumber> <SoftwareVersion>320</SoftwareVersion> <Description>EDGE305 Software Version 3.20</Description> </Model> */ TiXmlElement * model = new TiXmlElement( "Model" ); TiXmlElement * partnumber = new TiXmlElement( "PartNumber" ); partnumber->LinkEndChild(new TiXmlText("006-B0450-00")); TiXmlElement * version = new TiXmlElement( "SoftwareVersion" ); std::stringstream ss; ss << garmin.product.software_version; version->LinkEndChild(new TiXmlText( ss.str() )); TiXmlElement * descr = new TiXmlElement( "Description" ); descr->LinkEndChild(new TiXmlText(this->displayName)); model->LinkEndChild(partnumber); model->LinkEndChild(version); model->LinkEndChild(descr); device->LinkEndChild( model ); /* <Id>3333333333</Id> */ TiXmlElement * id = new TiXmlElement( "Id" ); ss.str(""); // empty stringstream ss << garmin.id; id->LinkEndChild(new TiXmlText(ss.str())); device->LinkEndChild(id); /* <DisplayName>Your name</DisplayName>*/ TiXmlElement * dispName = new TiXmlElement( "DisplayName" ); dispName->LinkEndChild(new TiXmlText(this->displayName)); device->LinkEndChild(dispName); TiXmlElement * massStorage = new TiXmlElement( "MassStorageMode" ); device->LinkEndChild(massStorage); /* <DataType> <Name>GPSData</Name> <File> <Specification> <Identifier>http://www.topografix.com/GPX/1/1</Identifier> <Documentation>http://www.topografix.com/GPX/1/1/gpx.xsd</Documentation> </Specification> <Location> <FileExtension>GPX</FileExtension> </Location> <TransferDirection>InputOutput</TransferDirection> </File> </DataType> */ TiXmlElement * dataTypes = new TiXmlElement( "DataType" ); massStorage->LinkEndChild(dataTypes); TiXmlElement * name = new TiXmlElement( "Name" ); name->LinkEndChild(new TiXmlText("GPSData")); dataTypes->LinkEndChild(name); TiXmlElement * file = new TiXmlElement( "File" ); dataTypes->LinkEndChild(file); TiXmlElement * spec = new TiXmlElement( "Specification" ); file->LinkEndChild(spec); TiXmlElement * identifier = new TiXmlElement( "Identifier" ); identifier->LinkEndChild(new TiXmlText("http://www.topografix.com/GPX/1/1")); spec->LinkEndChild(identifier); TiXmlElement * docu = new TiXmlElement( "Documentation" ); docu->LinkEndChild(new TiXmlText("http://www.topografix.com/GPX/1/1/gpx.xsd")); spec->LinkEndChild(docu); TiXmlElement * loc = new TiXmlElement( "Location" ); file->LinkEndChild(loc); TiXmlElement * fileEx = new TiXmlElement( "FileExtension" ); fileEx->LinkEndChild(new TiXmlText("GPX")); loc->LinkEndChild(fileEx); TiXmlElement * transferDir = new TiXmlElement( "TransferDirection" ); transferDir->LinkEndChild(new TiXmlText("InputOutput")); file->LinkEndChild(transferDir); /* <DataType> <Name>FitnessHistory</Name> <File> <Specification> <Identifier>http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2</Identifier> <Documentation>http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd</Documentation> </Specification> <Location> <FileExtension>TCX</FileExtension> </Location> <TransferDirection>OutputFromUnit</TransferDirection> </File> </DataType> */ dataTypes = new TiXmlElement( "DataType" ); massStorage->LinkEndChild(dataTypes); name = new TiXmlElement( "Name" ); name->LinkEndChild(new TiXmlText("FitnessHistory")); dataTypes->LinkEndChild(name); file = new TiXmlElement( "File" ); dataTypes->LinkEndChild(file); spec = new TiXmlElement( "Specification" ); file->LinkEndChild(spec); identifier = new TiXmlElement( "Identifier" ); identifier->LinkEndChild(new TiXmlText("http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2")); spec->LinkEndChild(identifier); docu = new TiXmlElement( "Documentation" ); docu->LinkEndChild(new TiXmlText("http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd")); spec->LinkEndChild(docu); loc = new TiXmlElement( "Location" ); file->LinkEndChild(loc); fileEx = new TiXmlElement( "FileExtension" ); fileEx->LinkEndChild(new TiXmlText("TCX")); loc->LinkEndChild(fileEx); transferDir = new TiXmlElement( "TransferDirection" ); transferDir->LinkEndChild(new TiXmlText("InputOutput")); file->LinkEndChild(transferDir); TiXmlPrinter printer; printer.SetIndent( "\t" ); doc.Accept( &printer ); string str = printer.Str(); if (Log::enabledDbg()) Log::dbg("GpsDevice::getDeviceDescription() Done: "+this->displayName ); return str; }
static PyObject* get_runs(PyObject* obj, PyObject* args) { garmin_unit garmin; if (!initialize_garmin(&garmin)) return NULL; garmin_data * data; if ( (data = garmin_get(&garmin, GET_RUNS)) == NULL ) { PyErr_SetString(PyExc_RuntimeError, "Unable to extract any data."); return NULL; } /* We should have a list with three elements: 1) The runs (which identify the track and lap indices) 2) The laps (which are related to the runs) 3) The tracks (which are related to the runs) */ garmin_data * tmpdata; garmin_list * runs = NULL; garmin_list * laps = NULL; garmin_list * tracks = NULL; tmpdata = garmin_list_data(data, 0); if ( tmpdata == NULL ) { PyErr_SetString(PyExc_RuntimeError, "Toplevel data missing element 0 (runs)"); return NULL; } runs = tmpdata->data; if ( runs == NULL ) { PyErr_SetString(PyExc_RuntimeError, "No runs extracted."); return NULL; } tmpdata = garmin_list_data(data, 1); if ( tmpdata == NULL ) { PyErr_SetString(PyExc_RuntimeError, "Toplevel data missing element 1 (laps)"); return NULL; } laps = tmpdata->data; if ( laps == NULL ) { PyErr_SetString(PyExc_RuntimeError, "No laps extracted."); return NULL; } tmpdata = garmin_list_data(data, 2); if ( tmpdata == NULL ) { PyErr_SetString(PyExc_RuntimeError, "Toplevel data missing element 2 (tracks)"); return NULL; } tracks = tmpdata->data; if ( tracks == NULL ) { PyErr_SetString(PyExc_RuntimeError, "No tracks extracted."); return NULL; } garmin_list_node * n; garmin_list_node * m; garmin_list_node * o; uint32 trk; uint32 f_lap; uint32 l_lap; uint32 l_idx; time_type start; /* Print some debug output if requested. */ if ( verbose != 0 ) { for ( m = laps->head; m != NULL; m = m->next ) { if ( get_lap_index(m->data,&l_idx) != 0 ) printf("[garmin] lap: index [%d]\n", l_idx); else printf("[garmin] lap: index [??]\n"); } } /* For each run, get its laps and track points. */ PyObject* dict = PyDict_New(); for ( n = runs->head; n != NULL; n = n->next ) { if ( get_run_track_lap_info(n->data, &trk, &f_lap, &l_lap) != 0 ) { time_type f_lap_start = 0; PyObject* run = PyDict_New(); PyObject* rlaps = PyDict_New(); PyDict_SetItem(run, PyString_FromString("track"), Py_BuildValue("i", trk)); PyDict_SetItem(run, PyString_FromString("first_lap"), Py_BuildValue("i", f_lap)); PyDict_SetItem(run, PyString_FromString("last_lap"), Py_BuildValue("i", l_lap)); PyDict_SetItem(run, PyString_FromString("type"), Py_BuildValue("i", (int)n->data->type)); /* TODO: Implement something similar for the other run types, D1000 and D1010 See src/run.c get_run_track_lap_info() for more information */ if (n->data->type == data_D1009) { D1009 * d1009; d1009 = n->data->data; PyDict_SetItem(run, PyString_FromString("multisport"), PyBool_FromLong(d1009->multisport)); switch (d1009->sport_type) { case D1000_running: PyDict_SetItem(run, PyString_FromString("sport"), PyString_FromString("running")); break; case D1000_biking: PyDict_SetItem(run, PyString_FromString("sport"), PyString_FromString("biking")); break; case D1000_other: PyDict_SetItem(run, PyString_FromString("sport"), PyString_FromString("other")); break; } } if (verbose != 0) printf("[garmin] run: track [%d], laps [%d:%d]\n",trk,f_lap,l_lap); for ( m = laps->head; m != NULL; m = m->next ) { if ( get_lap_index(m->data, &l_idx) != 0 ) { if ( l_idx >= f_lap && l_idx <= l_lap ) { PyObject* lap = PyDict_New(); if (verbose != 0) printf("[garmin] lap [%d] falls within laps [%d:%d]\n", l_idx,f_lap,l_lap); start = 0; get_lap_start_time(m->data, &start); if (start != 0) { if (l_idx == f_lap) f_lap_start = start; PyDict_SetItem(lap, PyString_FromString("start_time"), Py_BuildValue("i", (int)start)); PyDict_SetItem(lap, PyString_FromString("type"), Py_BuildValue("i", (int)m->data->type)); if (m->data->type == data_D1015) { D1015 * d1015; d1015 = m->data->data; PyDict_SetItem(lap, PyString_FromString("duration"), Py_BuildValue("i", d1015->total_time)); PyDict_SetItem(lap, PyString_FromString("distance"), Py_BuildValue("f", d1015->total_dist)); PyDict_SetItem(lap, PyString_FromString("max_speed"), Py_BuildValue("f", d1015->max_speed)); } PyObject * points = PyList_New(0); bool have_track = 0; bool done = 0; for ( o = tracks->head; o != NULL; o = o->next ) { if ( o->data != NULL ) { if (o->data->type == data_D311) { if ( ! have_track ) { D311 * d311; d311 = o->data->data; if ( d311->index == trk ) have_track = 1; } else /* We've reached the end of the track */ done = 1; } else if (o->data->type == data_D304 && have_track) { D304 * d304; d304 = o->data->data; PyObject* point = PyDict_New(); if (d304->posn.lat != 2147483647 && d304->posn.lon != 2147483647) { PyDict_SetItem(point, PyString_FromString("position"), Py_BuildValue("(ff)", SEMI2DEG(d304->posn.lat), SEMI2DEG(d304->posn.lon))); PyDict_SetItem(point, PyString_FromString("type"), Py_BuildValue("i", (int)o->data->type)); PyDict_SetItem(point, PyString_FromString("time"), Py_BuildValue("f", (float)(d304->time + TIME_OFFSET))); PyDict_SetItem(point, PyString_FromString("distance"), Py_BuildValue("f", d304->distance)); PyDict_SetItem(point, PyString_FromString("altitude"), Py_BuildValue("f", d304->alt)); PyDict_SetItem(point, PyString_FromString("heart_rate"), Py_BuildValue("i", d304->heart_rate)); if (d304->cadence != 255) PyDict_SetItem(point, PyString_FromString("cadence"), Py_BuildValue("i", d304->cadence)); PyList_Append(points, Py_BuildValue("N", point)); } } else if (have_track) printf("get_track: point type %d invalid!\n",o->data->type); } if ( done ) break; } PyDict_SetItem(lap, PyString_FromString("points"), Py_BuildValue("N", points)); } else PyErr_Warn(PyExc_Warning, "Start time of first lap not found."); PyDict_SetItem(rlaps, PyString_FromFormat("%d", (int)l_idx), Py_BuildValue("N", lap)); } } } PyDict_SetItem(run, PyString_FromString("laps"), Py_BuildValue("N", rlaps)); PyDict_SetItem(dict, PyString_FromFormat("%d", (int)f_lap_start), Py_BuildValue("N", run)); } } garmin_free_data(data); garmin_close(&garmin); return Py_BuildValue("N", dict); }