Example #1
0
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;


}
Example #6
0
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);  
}