Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Progress on gpx parsing - need to determine why failing

  • Loading branch information...
commit 7f9dd7dff04c2eee40bc3d470f514176b8b1ba98 1 parent e236feb
@scheibo authored
Showing with 165 additions and 50 deletions.
  1. +5 −11 Makefile
  2. +66 −24 activity.h
  3. +83 −14 gpx.c
  4. +1 −1  lib/mxml
  5. +1 −0  util.c
  6. +9 −0 util.h
View
16 Makefile
@@ -6,25 +6,19 @@ CFLAGS += $(WARN) $(DEBUG) -pthread
#TARGET = fitparse
#OBJECTS = activity.o fit.o tcx.o gpx.o
-default: util
+default: gpx
-all: mxml date
+all: gpx
-gpx: gpx.o mxml
- $(CC) $< lib/mxml/libmxml.a $(CFLAGS) -o $@
+gpx: gpx.o util.o lib/mxml/libmxml.a lib/date/libdate.a
+ $(CC) $^ $(CFLAGS) -o $@
gpx.o: gpx.c gpx.h lib/mxml/mxml.h
$(CC) $(CFLAGS) -Ilib/mxml -c $< -o $@
-util: util.o date
- $(CC) $< $(CFLAGS) -Llib/date -ldate -o $@
-
util.o: util.c lib/date/date.h
$(CC) $(CFLAGS) -Ilib/date -c $< -o $@
-mxml: lib/mxml/libmxml.a
-date: lib/date/libdate.a
-
lib/mxml/Makefile:
cd lib/mxml >/dev/null && ./configure >/dev/null
@@ -39,7 +33,7 @@ format:
clean:
rm -rf *.o util
- cd lib/mxml >/dev/null && git clean -f -d -x >/dev/null
+ cd lib/mxml >/dev/null && git clean -f -d -x >/dev/null && git checkout -- mxml.xml >/dev/null
cd lib/date >/dev/null && git clean -f -d -x >/dev/null
.SILENT: lib/mxml/Makefile mxml clean
View
90 activity.h
@@ -2,23 +2,71 @@
#define _ACTIVITY_H_
#include <stdint.h>
+#include <float.h>
+
+#define UNSET_TIMESTAMP UINT32_MAX
+#define UNSET_LATITUDE DBL_MAX
+#define UNSET_LONGITUDE DBL_MAX
+#define UNSET_ALTITUDE INT32_MAX
+#define UNSET_DISTANCE UINT32_MAX
+#define UNSET_SPEED UINT32_MAX
+#define UNSET_POWER UINT16_MAX
+#define UNSET_GRADE INT16_MAX
+#define UNSET_HEART_RATE UINT8_MAX
+#define UNSET_CADENCE UINT8_MAX
+#define UNSET_LR_BALANCE UINT8_MAX
+#define UNSET_TEMPERATURE INT8_MAX
typedef struct DataPoint {
- uint32_t timestamp; /* s since Unix Epoch UTC */
- double latitude; /* degrees */
- double longitude; /* degrees */
- int32_t altitude; /* m */
- uint32_t distance; /* 100 * m */
- uint32_t speed; /* 1000 * m/s */
- uint16_t power; /* watts */
- int16_t grade; /* 100 * % */
- uint8_t heart_rate; /* bpm */
- uint8_t cadence; /* rpm */
- uint8_t lr_balance; /* ? */
- int8_t temperature; /* C */
+ uint32_t timestamp; /* s since Unix Epoch UTC */
+ double latitude; /* degrees */
+ double longitude; /* degrees */
+ int32_t altitude; /* 1000 * m */
+ uint32_t distance; /* 100 * m */
+ uint32_t speed; /* 1000 * m/s */
+ uint16_t power; /* watts */
+ int16_t grade; /* 100 * % */
+ uint8_t heart_rate; /* bpm */
+ uint8_t cadence; /* rpm */
+ uint8_t lr_balance; /* ? */
+ int8_t temperature; /* C */
struct DataPoint *next;
} DataPoint;
+#define UNSET_DATA_POINT \
+ { \
+ UNSET_TIMESTAMP, UNSET_LATITUDE, UNSET_LONGITUDE, UNSET_ALTITUDE, \
+ UNSET_DISTANCE, UNSET_SPEED, UNSET_POWER, UNSET_GRADE, \
+ UNSET_HEART_RATE, UNSET_CADENCE, UNSET_LR_BALANCE, UNSET_TEMPERATURE, \
+ NULL \
+ }
+
+#define CLEAR_DATA_POINT(d) \
+ do { \
+ (d).timestamp = UNSET_TIMESTAMP; \
+ (d).latitude = UNSET_LATITUDE; \
+ (d).longitude = UNSET_LONGITUDE; \
+ (d).altitude = UNSET_ALTITUDE; \
+ (d).distance = UNSET_DISTANCE; \
+ (d).speed = UNSET_SPEED; \
+ (d).power = UNSET_POWER; \
+ (d).grade = UNSET_GRADE; \
+ (d).heart_rate = UNSET_HEART_RATE; \
+ (d).lr_balance = UNSET_LR_BALANCE; \
+ (d).temperature = UNSET_TEMPERATURE; \
+ (d).next = NULL; \
+ } while (0)
+
+/* TODO debug */
+static inline void print_data_point(DataPoint *d) {
+ fprintf(stderr,
+ "time: %u, lat: %f, lon: %f, alt: %d, dist: %u, speed: %u, pow: %u, "
+ "grd: %d, hr: %u, cad: %u, bal: %u, temp: %d, next: %p\n",
+ d->timestamp, d->latitude, d->longitude, d->altitude, d->distance,
+ d->speed, d->power, d->grade, d->heart_rate, d->cadence,
+ d->lr_balance, d->temperature, (void *)d->next);
+}
+
/*
//TODO could also do these per lap
typedef struct Summary {
@@ -48,7 +96,6 @@ typedef struct Summary {
} Summary;
*/
-
typedef enum {
/* Swimming, */
Running,
@@ -58,25 +105,20 @@ typedef enum {
typedef struct {
Sport sport;
- uint32_t *laps; /* TODO array of timestamps, always at least one */
+ uint32_t *laps; /* TODO array of timestamps, always at least one */
DataPoint *data_points;
DataPoint *last_point;
/*
//Summary summary; // can include derived statistics (totalAscent, NP, avg)
- //Summary * lap_summaries; // can include derived statistics (totalAscent, NP, avg)
+ //Summary * lap_summaries; // can include derived statistics (totalAscent, NP,
+ avg)
*/
} Activity;
typedef int (*ReadFn)(char *, Activity *);
typedef int (*WriteFn)(char *, Activity *);
-typedef enum {
- CSV,
- GPX,
- TCX,
- FIT,
- UnknownFileFormat
-} FileFormat;
+typedef enum { CSV, GPX, TCX, FIT, UnknownFileFormat } FileFormat;
#define activity_new() \
{ UnknownSport, NULL, NULL }
@@ -93,8 +135,8 @@ int activity_write(Activity *activity, char *filename);
/* helper functions - could just call the *_read or *_write function directly */
int activity_read_format(Activity *activity, char *filename, FileFormat format);
-int activity_write_format(Activity *activity, char *filename, FileFormat format);
-
+int activity_write_format(Activity *activity, char *filename,
+ FileFormat format);
/*****************
* Read all individual points and compare it to summary data
View
97 gpx.c
@@ -1,44 +1,113 @@
#include <stdio.h>
+#include <stdlib.h>
#include <ctype.h>
#include "activity.h"
#include "mxml.h"
+#include "util.h"
-/*
-Activity *activity = activity_new();
-int error = gpx_read("file.gpx", &activity);
-activity_destroy(activity);
-*/
+typedef enum { false, true } bool;
+
+typedef struct {
+ bool metadata;
+ bool first_element;
+ bool first_time;
+ DataPoint data;
+} State;
int allspace(const char *str) {
- while (isspace(*str)) { str++; }
+ while (isspace(*str)) {
+ str++;
+ }
return !*str;
}
-static void sax_cb(mxml_node_t *node, mxml_sax_event_t event, void *sax_data) {
- const char *name, *data;
+static int sax_cb(mxml_node_t *node, mxml_sax_event_t event, void *sax_data) {
+ const char *name, *attr, *data;
+ char *end;
+ State *state = (State *)sax_data;
+
if (event == MXML_SAX_ELEMENT_OPEN) {
name = mxmlGetElement(node);
- fprintf(stderr, "open: <%s>\n", name);
+ if (state->metadata) return 0;
+
+ name = mxmlGetElement(node);
+ if (state->first_element && strcmp(name, "gpx")) {
+ fprintf(stderr, "error\n");
+ return 1; /* stop reading the file */
+ }
+
+ if (!strcmp(name, "metadata")) {
+ state->metadata = true;
+ } else if (!strcmp(name, "trkpt")) {
+ attr = mxmlElementGetAttr(node, "lat");
+ if (attr) {
+ state->data.latitude = strtod(attr, &end);
+ if (*end) state->data.latitude = UNSET_LATITUDE;
+ }
+ attr = mxmlElementGetAttr(node, "lon");
+ if (attr) {
+ state->data.longitude = strtod(attr, &end);
+ if (*end) state->data.longitude = UNSET_LONGITUDE;
+ }
+ }
+ state->first_element = false;
} else if (event == MXML_SAX_ELEMENT_CLOSE) {
name = mxmlGetElement(node);
data = mxmlGetOpaque(node);
- if (!allspace(data)) {
- fprintf(stderr, "data: %d '%s'\n", mxmlGetType(node), data);
+
+ if (!strcmp(name, "metadata")) {
+ state->metadata = false;
+ } else if (state->metadata) {
+ return 0;
+ } else if (!strcmp(name, "time")) {
+ state->data.timestamp = parse_timestamp(data);
+ if (!state->data.timestamp) state->data.timestamp = UNSET_TIMESTAMP;
+ } else if (!strcmp(name, "ele")) {
+ state->data.altitude = (int32_t)(strtod(data, &end) * 1000);
+ if (*end) state->data.altitude = UNSET_ALTITUDE;
+ } else if (!strcmp(name, "gpxtpx:hr")) {
+ state->data.heart_rate = (uint8_t)strtod(data, &end);
+ if (*end) state->data.heart_rate = UNSET_HEART_RATE;
+ } else if (!strcmp(name, "gpxdata:hr")) {
+ state->data.heart_rate = (uint8_t)strtod(data, &end);
+ if (*end) state->data.heart_rate = UNSET_HEART_RATE;
+ } else if (!strcmp(name, "gpxdata:temp")) {
+ state->data.temperature = (int8_t)strtod(data, &end);
+ if (*end) state->data.temperature = UNSET_TEMPERATURE;
+ } else if (!strcmp(name, "gpxdata:cadence")) {
+ state->data.cadence = (uint8_t)strtod(data, &end);
+ if (*end) state->data.cadence = UNSET_CADENCE;
+ } else if (!strcmp(name, "gpxdata:bikepower")) {
+ state->data.power = (uint16_t)strtod(data, &end);
+ if (*end) state->data.power = UNSET_POWER;
+ } else if (!strcmp(name, "trkpt")) {
+ /* TODO */
+ print_data_point(&(state->data));
+ CLEAR_DATA_POINT(state->data);
}
- fprintf(stderr, "close: </%s>\n", name);
} else if (event == MXML_SAX_DATA) {
mxmlRetain(node);
}
+
+ return 0;
}
int gpx_read(char *filename, Activity *activity) {
FILE *f = NULL;
+ State state = {false /* metadata */, true /* first_element */,
+ true /* first_time */, UNSET_DATA_POINT};
if (!(f = fopen(filename, "r"))) {
return 1;
}
- mxmlSAXLoadFile(NULL, f, MXML_OPAQUE_CALLBACK, sax_cb, NULL);
+ if (!mxmlSAXLoadFile(NULL, f, MXML_OPAQUE_CALLBACK, sax_cb, (void *)&state)) {
+ fprintf(stderr, "failed\n");
+ fclose(f);
+ return 1;
+ }
+
+ fprintf(stderr, "Made it\n");
fclose(f);
return 0;
@@ -59,7 +128,7 @@ int gpx_write(char *filename, Activity *activity) {
/* TODO */
int main(int argc, char *argv[]) {
- Activity activity = activity_new();
+ Activity activity = activity_new();
int ret = gpx_read(argv[1], &activity);
/*activity_destroy(&activity);*/
return ret;
2  lib/mxml
@@ -1 +1 @@
-Subproject commit 01572c4778180aee7e6c4d8ae65b874c60d98e2d
+Subproject commit d03289c464ae6f50c47111e7de8e6810da684a31
View
1  util.c
@@ -1,6 +1,7 @@
#include <stdint.h>
#include <time.h>
+#include "util.h"
#include "date.h"
/* Parse an ISO_8601 timestamp */
View
9 util.h
@@ -0,0 +1,9 @@
+#ifndef _UTIL_H_
+#define _UTIL_H_
+
+#include <stdint.h>
+
+uint32_t parse_timestamp(const char *date);
+int format_timestamp(char *buf, uint32_t timestamp);
+
+#endif /* _UTIL_H_ */
Please sign in to comment.
Something went wrong with that request. Please try again.