summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--display-gtk.h3
-rw-r--r--dive.h10
-rw-r--r--gtk-gui.c18
-rw-r--r--uemis-downloader.c500
-rw-r--r--uemis.c77
-rw-r--r--uemis.h4
6 files changed, 316 insertions, 296 deletions
diff --git a/display-gtk.h b/display-gtk.h
index b524f5e50..f88d96633 100644
--- a/display-gtk.h
+++ b/display-gtk.h
@@ -113,7 +113,6 @@ typedef gint (*sort_func_t)(GtkTreeModel *model,
extern GtkTreeViewColumn *tree_view_column(GtkWidget *tree_view, int index, const char *title,
data_func_t data_func, unsigned int flags);
-GError *uemis_download(const char *path, char **xml_buffer,
- progressbar_t *progress, GtkDialog *dialog, gboolean force_download);
+GError *uemis_download(const char *path, progressbar_t *progress, GtkDialog *dialog, gboolean force_download);
#endif
diff --git a/dive.h b/dive.h
index 4eb81752f..e03399ec1 100644
--- a/dive.h
+++ b/dive.h
@@ -405,6 +405,16 @@ static inline struct dive *get_dive(int nr)
return dive_table.dives[nr];
}
+static inline struct dive *get_dive_by_diveid(int diveid, int deviceid)
+{
+ int i;
+ for (i = 0; i < dive_table.nr; i++)
+ if (dive_table.dives[i]->dc.diveid == diveid &&
+ dive_table.dives[i]->dc.deviceid == deviceid)
+ return dive_table.dives[i];
+ return NULL;
+}
+
/*
* Iterate over each dive, with the first parameter being the index
* iterator variable, and the second one being the dive one.
diff --git a/gtk-gui.c b/gtk-gui.c
index 81f93ca1e..6f08255bd 100644
--- a/gtk-gui.c
+++ b/gtk-gui.c
@@ -1644,22 +1644,6 @@ void import_files(GtkWidget *w, gpointer data)
restore_tree_state();
}
-static GError *setup_uemis_import(device_data_t *data)
-{
- GError *error = NULL;
- char *buf = NULL;
-
- error = uemis_download(data->devname, &buf, &data->progress, data->dialog, data->force_download);
- if (buf && strlen(buf) > 1) {
-#if UEMIS_DEBUG > 3
- fprintf(debugfile, "xml buffer \"%s\"\n\n", buf);
-#endif
- parse_xml_buffer("Uemis Download", buf, strlen(buf), TRUE, &error);
- mark_divelist_changed(TRUE);
- }
- return error;
-}
-
static GtkWidget *import_dive_computer(device_data_t *data, GtkDialog *dialog)
{
GError *error;
@@ -1667,7 +1651,7 @@ static GtkWidget *import_dive_computer(device_data_t *data, GtkDialog *dialog)
/* HACK to simply include the Uemis Zurich in the list */
if (! strcmp(data->vendor, "Uemis") && ! strcmp(data->product, "Zurich")) {
- error = setup_uemis_import(data);
+ error = uemis_download(data->devname, &data->progress, data->dialog, data->force_download);
} else {
error = do_import(data);
}
diff --git a/uemis-downloader.c b/uemis-downloader.c
index 9577c48cc..c80b1e929 100644
--- a/uemis-downloader.c
+++ b/uemis-downloader.c
@@ -44,11 +44,12 @@ static int mbuf_size = 0;
struct argument_block {
const char *mountpath;
- char **xml_buffer;
progressbar_t *progress;
gboolean force_download;
};
+static int nr_divespots = 0;
+
static int import_thread_done = 0, import_thread_cancelled;
static const char *progress_bar_text = "";
static double progress_bar_fraction = 0.0;
@@ -66,6 +67,72 @@ static GError *error(const char *fmt, ...)
return error;
}
+/* helper function to parse the Uemis data structures */
+static void uemis_ts(char *buffer, void *_when)
+{
+ struct tm tm;
+ timestamp_t *when = _when;
+
+ memset(&tm, 0, sizeof(tm));
+ sscanf(buffer,"%d-%d-%dT%d:%d:%d",
+ &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
+ &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
+ tm.tm_mon -= 1;
+ tm.tm_year -= 1900;
+ *when = utc_mktime(&tm);
+}
+
+/* float minutes */
+static void uemis_duration(char *buffer, duration_t *duration)
+{
+ duration->seconds = atof(buffer) * 60 + 0.5;
+}
+
+/* int cm */
+static void uemis_depth(char *buffer, depth_t *depth)
+{
+ depth->mm = atoi(buffer) * 10;
+}
+
+static void uemis_get_index(char *buffer, int *idx)
+{
+ *idx = atoi(buffer);
+}
+
+/* space separated */
+static void uemis_add_string(char *buffer, char **text)
+{
+ if (!buffer || !*buffer)
+ return;
+ if (!*text) {
+ *text = strdup(buffer);
+ } else {
+ char *buf = malloc(strlen(buffer) + strlen(*text) + 2);
+ strcpy(buf, *text);
+ strcat(buf, " ");
+ strcat(buf, buffer);
+ free(*text);
+ *text = buf;
+ }
+}
+
+/* still unclear if it ever reports lbs */
+static void uemis_get_weight(char *buffer, weightsystem_t *weight, int diveid)
+{
+ weight->weight.grams = uemis_get_weight_unit(diveid) ?
+ lbs_to_grams(atof(buffer)) : atof(buffer) * 1000;
+ weight->description = strdup("unknown");
+}
+
+static struct dive *uemis_start_dive(int deviceid)
+{
+ struct dive *dive = alloc_dive();
+ dive->downloaded = TRUE;
+ dive->dc.model = strdup("Uemis Zurich");
+ dive->dc.deviceid = deviceid;
+ return dive;
+}
+
/* send text to the importer progress bar */
static void uemis_info(const char *fmt, ...)
{
@@ -136,16 +203,7 @@ static gboolean uemis_init(const char *path)
close (reqtxt_file);
/* It would be nice if we could simply go back to the first set of
- * ANS files. Something like the below - unfortunately this is known
- * to fail - more information from Uemis is needed here.
- * Without code like this it is very easy when downloading large amounts
- * of dives to run out of space on the dive computer - which can only
- * be fixed by unmounting and rebooting the DC
- * reqtxt_file = g_open(reqtxt_path, O_RDWR | O_CREAT | O_TRUNC, 0666);
- * write(reqtxt_file, "n0001", 5);
- * close(reqtxt_file);
- * filenr = 1;
- */
+ * ANS files. But with a FAT filesystem that isn't possible */
ans_path = g_build_filename(path, "ANS", NULL);
number_of_files = number_of_file(ans_path);
g_free(ans_path);
@@ -246,184 +304,6 @@ static void buffer_add(char **buffer, int *buffer_size, char *buf)
#endif
}
-#define PATTERN1 "<val key=\"%s\">%s"
-#define PATTERN2 "\n<int>%d</int>"
-static gboolean get_tag_int_value(char *buffer, char *tag, int *value, char **next_ptr)
-{
- char *ptr = buffer;
- int len;
- char *format;
-
- if (!ptr || !value)
- return FALSE;
- len = strlen(PATTERN1) + strlen(PATTERN2) + strlen(tag);
- format = malloc(len);
- snprintf(format, len, PATTERN1, tag, "");
- ptr = strstr(ptr, format);
- if (!ptr)
- return FALSE;
- snprintf(format, len, PATTERN1, tag, PATTERN2);
- if (sscanf(ptr, format, value) != 1)
- return FALSE;
- if (next_ptr)
- *next_ptr = ptr + 1;
- return TRUE;
-}
-
-static gboolean get_tag_string_value(char *buffer, char *tag, char **value)
-{
- char *eptr, *ptr = buffer;
- int len;
- char *format;
-
- if (!ptr || !value)
- return FALSE;
- len = strlen(PATTERN1) + strlen(tag);
- format = malloc(len);
- snprintf(format, len, PATTERN1, tag, "");
- ptr = strstr(ptr, format);
- if (!ptr)
- return FALSE;
- eptr = strstr(ptr, "</string>");
- if (!eptr)
- return FALSE;
- *eptr = '\0';
- *value = strdup(ptr + strlen(format) + 9);
- *eptr = '<';
- return TRUE;
-}
-
-#define PATTERN4 "\n<float>%lf</float>"
-static gboolean get_tag_double_value(char *buffer, char *tag, double *value, char **next_ptr)
-{
- char *ptr = buffer;
- int len;
- char *format;
-
- if (!ptr || !value)
- return FALSE;
- len = strlen(PATTERN1) + strlen(PATTERN4) + strlen(tag);
- format = malloc(len);
- snprintf(format, len, PATTERN1, tag, "");
- ptr = strstr(ptr, format);
- if (!ptr)
- return FALSE;
- snprintf(format, len, PATTERN1, tag, PATTERN4);
- if (sscanf(ptr, format, value) != 1)
- return FALSE;
- if (next_ptr)
- *next_ptr = ptr + 1;
- return TRUE;
-}
-
-static char *get_xml_for_int(char *buf, char *tag)
-{
- int value;
- char *xml;
- if (get_tag_int_value(buf, tag, &value, NULL)) {
- int len = 20 + 2 * strlen(tag);
- xml = malloc(len);
- snprintf(xml, len, "<%s>%d</%s>\n", tag, value, tag);
- }
- return xml;
-}
-
-static const char *suit[] = { "", "wetsuit", "semidry", "drysuit" };
-static const char *suit_type[] = { "", "shorty", "vest", "long john", "jacket", "full suit", "2 pcs full suit" };
-static const char *suit_thickness[] = { "", "0.5-2mm", "2-3mm", "3-5mm", "5-7mm", "8mm+", "membrane" };
-static char *convert_dive_details(char *buf, uint8_t *hdr)
-{
- char *conv_buffer = NULL;
- int conv_size = 0;
- char *ptr, *eptr;
- double doublevalue;
- double weight;
- char *stringvalue;
- char textbuf[200];
- int suit_idx, suit_type_idx, suit_thickness_idx;
-
- /* we want to throw away what is duplicate and clean up and
- * parse the userful entries */
- ptr = strstr(buf, "<val key=\"logfilenr\">");
- if (!ptr)
- return NULL;
- eptr = strstr(ptr + 1, "<val");
- *eptr = '\0';
- buffer_add(&conv_buffer, &conv_size, ptr);
- *eptr = '<';
- buffer_add(&conv_buffer, &conv_size, get_xml_for_int(eptr, "altitude"));
- buffer_add(&conv_buffer, &conv_size, get_xml_for_int(eptr, "decoindex"));
- buffer_add(&conv_buffer, &conv_size, get_xml_for_int(eptr, "consumption"));
- if (get_tag_double_value(eptr, "f32Weight", &doublevalue, NULL)) {
- weight = hdr[24] ? lbs_to_grams(doublevalue) / 1000.0 : doublevalue;
- snprintf(textbuf, sizeof(textbuf),
- "<weightsystem weight='%.3lf' description='unknown' />\n", weight);
- buffer_add(&conv_buffer, &conv_size, textbuf);
- }
- if (get_tag_string_value(eptr, "notes", &stringvalue)) {
- buffer_add(&conv_buffer, &conv_size, "<notes>");
- buffer_add(&conv_buffer, &conv_size, stringvalue);
- buffer_add(&conv_buffer, &conv_size, "</notes>\n");
- }
- if (get_tag_int_value(eptr, "u8DiveSuit", &suit_idx, NULL) &&
- get_tag_int_value(eptr, "u8DiveSuitType", &suit_type_idx, NULL) &&
- get_tag_int_value(eptr, "u8SuitThickness", &suit_thickness_idx, NULL) &&
- suit_idx >= 0 && suit_idx < sizeof(suit) &&
- suit_type_idx >= 0 && suit_type_idx < sizeof(suit_type) &&
- suit_thickness_idx >= 0 && suit_thickness_idx < sizeof(suit_thickness)) {
- snprintf(textbuf, sizeof(textbuf), "<suit>%s %s %s</suit>\n",
- suit[suit_idx], suit_type[suit_type_idx], suit_thickness[suit_thickness_idx]);
- buffer_add(&conv_buffer, &conv_size, textbuf);
- }
- return conv_buffer;
-}
-
-/* this is more interesting - insert the additional data in the dive
- * it belongs to - no idea why Uemis splits out the dive data in this
- * odd way, but we have to re-assemble it here */
-static void buffer_insert(char **buffer, int *buffer_size, char *buf)
-{
- char *ptr, *endptr, *b64, *cbuf;
- int obj_dive;
- int obj_log;
- int offset, len;
- uint8_t hdr[27];
-
- /* since we want to insert into the buffer... if there's
- * nothing there, this makes absolutely no sense so just
- * bail */
- if (!buf || !*buffer)
- return;
- endptr = *buffer + strlen(*buffer);
- /* now figure out the object_id of buf and find the matching
- * spot in buffer */
- if (!get_tag_int_value(buf, "logfilenr", &obj_dive, NULL))
- return;
- ptr = *buffer;
- while (ptr < endptr) {
- if (!get_tag_int_value(ptr, "object_id", &obj_log, &ptr))
- return;
- if (obj_dive == obj_log)
- break;
- }
- ptr = strstr(ptr, "<val key=\"file_content\">");
- if (!ptr)
- return;
- /* this is where the base64 data starts; we need to extract
- * some info from that in order to make sense of the data in
- * the dive info */
- b64 = strstr(ptr, "<bin>") + 5;
- decode(b64, hdr, 36);
- cbuf = convert_dive_details(buf, hdr);
- offset = ptr - *buffer;
- len = strlen(cbuf);
- *buffer_size += len;
- *buffer = realloc(*buffer, *buffer_size);
- ptr = *buffer + offset;
- memmove(ptr + len, ptr, strlen(*buffer) - offset + 1);
- memmove(ptr, cbuf, len);
-}
-
/* are there more ANS files we can check? */
static gboolean next_file(int max)
{
@@ -436,12 +316,12 @@ static gboolean next_file(int max)
/* ultra-simplistic; it doesn't deal with the case when the object_id is
* split across two chunks. It also doesn't deal with the discrepancy between
* object_id and dive number as understood by the dive computer */
-static void show_progress(char *buf)
+static void show_progress(char *buf, char *what)
{
char *object;
object = strstr(buf, "object_id");
if (object) {
- /* let the user know which dive we are working on */
+ /* let the user know what we are working on */
char tmp[10];
char *p = object + 14;
char *t = tmp;
@@ -450,7 +330,7 @@ static void show_progress(char *buf)
while (*p != '{' && t < tmp + 9)
*t++ = *p++;
*t = '\0';
- uemis_info(_("Reading dive %s"), tmp);
+ uemis_info(_("Reading %s %s"), what, tmp);
}
}
}
@@ -470,6 +350,7 @@ static gboolean uemis_get_answer(const char *path, char *request, int n_param_in
char sb[BUFLEN];
char fl[13];
char tmp[101];
+ char *what = _("data");
gboolean searching = TRUE;
gboolean assembling_mbuf = FALSE;
gboolean ismulti = FALSE;
@@ -485,9 +366,16 @@ static gboolean uemis_get_answer(const char *path, char *request, int n_param_in
str_append_with_delim(sb, request);
for (i = 0; i < n_param_in; i++)
str_append_with_delim(sb, param_buff[i]);
- if (! strcmp(request, "getDivelogs") || ! strcmp(request, "getDeviceData") || ! strcmp(request, "getDirectory")) {
+ if (! strcmp(request, "getDivelogs") || ! strcmp(request, "getDeviceData") || ! strcmp(request, "getDirectory") ||
+ ! strcmp(request, "getDivespot") || strcmp(request, "getDive")) {
answer_in_mbuf = TRUE;
str_append_with_delim(sb, "");
+ if (! strcmp(request, "getDivelogs"))
+ what = _("divelog entry id");
+ else if (!strcmp(request, "getDivespot"))
+ what = _("divespot data id");
+ else if (!strcmp(request, "getDive"))
+ what = _("additional data dive id");
}
str_append_with_delim(sb, "");
file_length = strlen(sb);
@@ -567,9 +455,9 @@ static gboolean uemis_get_answer(const char *path, char *request, int n_param_in
char *buf = malloc(size - 2);
lseek(ans_file, 3, SEEK_CUR);
read(ans_file, buf, size - 3);
- buf[size -3 ] = '\0';
+ buf[size - 3] = '\0';
buffer_add(&mbuf, &mbuf_size, buf);
- show_progress(buf);
+ show_progress(buf, what);
free(buf);
param_buff[3]++;
}
@@ -592,6 +480,8 @@ static gboolean uemis_get_answer(const char *path, char *request, int n_param_in
lseek(ans_file, 3, SEEK_CUR);
read(ans_file, buf, size - 3);
buf[size - 3] = '\0';
+ buffer_add(&mbuf, &mbuf_size, buf);
+ show_progress(buf, what);
#if UEMIS_DEBUG > 3
fprintf(debugfile, "::r %s \"%s\"\n", ans_path, buf);
#endif
@@ -618,22 +508,105 @@ static gboolean uemis_get_answer(const char *path, char *request, int n_param_in
return found_answer;
}
-/* Turn what we get from the dive computer into something that we can
- * pass to the parse_xml function. If this is a divelog, then the
- * last 'object_id' that we see is returned as our current
- * approximation of a last dive number */
-static char *process_raw_buffer(char *inbuf, char **max_divenr)
+static void parse_divespot(char *buf)
+{
+ char *bp = buf + 1;
+ char *tp = next_token(&bp);
+ char *tag, *type, *val;
+ char locationstring[255] = "";
+ int divespot, len;
+ double latitude, longitude;
+
+
+ if (strcmp(tp, "divespot"))
+ return;
+ do
+ tag = next_token(&bp);
+ while (*tag && strcmp(tag, "object_id"));
+ if (! *tag)
+ return;
+ type = next_token(&bp);
+ val = next_token(&bp);
+ divespot = atoi(val);
+ do {
+ tag = next_token(&bp);
+ type = next_token(&bp);
+ val = next_token(&bp);
+ if (!strcmp(type, "string") && *val && strcmp(val, " ")) {
+ len = strlen(locationstring);
+ snprintf(locationstring + len, sizeof(locationstring) - len,
+ "%s%s", len ? ", " : "", val);
+ } else if (!strcmp(type, "float")) {
+ if (!strcmp(tag, "longitude"))
+ longitude = atof(val);
+ else if (!strcmp(tag, "latitude"))
+ latitude = atof(val);
+ }
+ } while (tag && *tag);
+ uemis_set_divelocation(divespot, strdup(locationstring), latitude, longitude);
+}
+
+static void track_divespot(char *val, int diveid, char **location, double *latitude, double *longitude)
+{
+ int id = atoi(val);
+ if (id >= 0 && id > nr_divespots)
+ nr_divespots = id;
+ uemis_mark_divelocation(diveid, id, location, latitude, longitude);
+ return;
+}
+
+static char *suit[] = { "", "wetsuit", "semidry", "drysuit" };
+static char *suit_type[] = { "", "shorty", "vest", "long john", "jacket", "full suit", "2 pcs full suit" };
+static char *suit_thickness[] = { "", "0.5-2mm", "2-3mm", "3-5mm", "5-7mm", "8mm+", "membrane" };
+
+static void parse_tag(struct dive *dive, char *tag, char *val)
+{
+ /* we can ignore computer_id, water and gas as those are redundant
+ * with the binary data and would just get overwritten */
+ if (! strcmp(tag, "date"))
+ uemis_ts(val, &dive->when);
+ else if (!strcmp(tag, "duration"))
+ uemis_duration(val, &dive->duration);
+ else if (!strcmp(tag, "depth"))
+ uemis_depth(val, &dive->maxdepth);
+ else if (!strcmp(tag, "file_content"))
+ uemis_parse_divelog_binary(val, dive);
+ else if (!strcmp(tag, "altitude"))
+ uemis_get_index(val, &dive->surface_pressure.mbar);
+ else if (!strcmp(tag, "f32Weight"))
+ uemis_get_weight(val, &dive->weightsystem[0], dive->dc.diveid);
+ else if (!strcmp(tag, "notes"))
+ uemis_add_string(val, &dive->notes);
+ else if (!strcmp(tag, "u8DiveSuit"))
+ uemis_add_string(suit[atoi(val)], &dive->suit);
+ else if (!strcmp(tag, "u8DiveSuitType"))
+ uemis_add_string(suit_type[atoi(val)], &dive->suit);
+ else if (!strcmp(tag, "u8SuitThickness"))
+ uemis_add_string(suit_thickness[atoi(val)], &dive->suit);
+}
+
+/* This function is called for both divelog and dive information that we get
+ * from the SDA (what an insane design, btw). The object_id in the divelog
+ * matches the logfilenr in the dive information (which has its own, often
+ * different object_id) - we use this as the diveid.
+ * We create the dive when parsing the divelog and then later, when we parse
+ * the dive information we locate the already created dive via its diveid.
+ * Most things just get parsed and converted into our internal data structures,
+ * but the dive location API is even more crazy. We just get an id that is an
+ * index into yet another data store that we read out later. In order to
+ * correctly populate the location and gps data from that we need to remember
+ * the adresses of those fields for every dive that references the divespot. */
+static void process_raw_buffer(int deviceid, char *inbuf, char **max_divenr)
{
char *buf = strdup(inbuf);
char *tp, *bp, *tag, *type, *val;
gboolean done = FALSE;
int inbuflen = strlen(inbuf);
char *endptr = buf + inbuflen;
- char *conv_buffer = NULL;
- int conv_buffer_size = 0;
gboolean log = FALSE;
char *sections[10];
int s, nr_sections = 0;
+ struct dive *dive = NULL;
bp = buf + 1;
tp = next_token(&bp);
@@ -642,23 +615,19 @@ static char *process_raw_buffer(char *inbuf, char **max_divenr)
log = TRUE;
tp = next_token(&bp);
if (strcmp(tp,"1.0") != 0)
- return NULL;
+ return;
} else if (strcmp(tp, "dive") == 0) {
/* this is dive detail */
tp = next_token(&bp);
if (strcmp(tp,"1.0") != 0)
- return NULL;
+ return;
} else {
/* don't understand the buffer */
- return NULL;
+ return;
}
if (log)
- buffer_add(&conv_buffer, &conv_buffer_size,
- "<dive type=\"uemis\" ref=\"divelog\" version=\"1.0\">\n");
+ dive = uemis_start_dive(deviceid);
while (!done) {
- char *tmp;
- int tmp_size;
-
/* the valid buffer ends with a series of delimiters */
if (bp >= endptr - 2 || !strcmp(bp, "{{"))
break;
@@ -687,36 +656,38 @@ static char *process_raw_buffer(char *inbuf, char **max_divenr)
if (log && ! strcmp(tag, "object_id")) {
free(*max_divenr);
*max_divenr = strdup(val);
+ dive->dc.diveid = atoi(val);
+ } else if (!log && ! strcmp(tag, "logfilenr")) {
+ /* this one tells us which dive we are adding data to */
+ dive = get_dive_by_diveid(atoi(val), deviceid);
+ } else if (!log && dive && ! strcmp(tag, "divespot_id")) {
+ track_divespot(val, dive->dc.diveid, &dive->location, &dive->latitude, &dive->longitude);
+ } else if (dive) {
+ parse_tag(dive, tag, val);
}
- if (! strcmp(tag, "file_content")) {
- tmp_size = 45 + strlen(tag) + strlen(val);
+ if (log && ! strcmp(tag, "file_content"))
done = TRUE;
- } else {
- tmp_size = 28 + strlen(tag) + 2 * strlen(type) + strlen(val);
- }
- tmp = malloc(tmp_size);
- snprintf(tmp, tmp_size, "<val key=\"%s\">\n<%s>%s</%s>\n</val>\n",
- tag, type, val, type);
- buffer_add(&conv_buffer, &conv_buffer_size, tmp);
- free(tmp);
/* done with one dive (got the file_content tag), but there could be more:
* a '{' indicates the end of the record - but we need to see another "{{"
* later in the buffer to know that the next record is complete (it could
* be a short read because of some error */
if (done && ++bp < endptr && *bp != '{' && strstr(bp, "{{")) {
done = FALSE;
- buffer_add(&conv_buffer, &conv_buffer_size,
- "</dive>\n<dive type=\"uemis\" ref=\"divelog\" version=\"1.0\">\n");
+ record_dive(dive);
+ mark_divelist_changed(TRUE);
+ dive = uemis_start_dive(deviceid);
}
}
if (log) {
- buffer_add(&conv_buffer, &conv_buffer_size, "</dive>\n");
+ if (dive->dc.diveid) {
+ record_dive(dive);
+ mark_divelist_changed(TRUE);
+ } else { /* partial dive */
+ free(dive);
+ }
}
free(buf);
-#if UEMIS_DEBUG > 3
- fprintf(debugfile,"converted to \"%s\"\n", conv_buffer);
-#endif
- return strdup(conv_buffer);
+ return;
}
static char *get_divenr(char *deviceidstr)
@@ -724,38 +695,34 @@ static char *get_divenr(char *deviceidstr)
int deviceid, i, maxdiveid = 0;
char divenr[10];
- if (sscanf(deviceidstr, "%d", &deviceid) != 1)
- return "0";
+ deviceid = atoi(deviceidstr);
for (i = 0; i < dive_table.nr; i++) {
struct divecomputer *dc = &dive_table.dives[i]->dc;
if (dc->deviceid == deviceid && dc->diveid > maxdiveid)
maxdiveid = dc->diveid;
}
snprintf(divenr, 10, "%d", maxdiveid);
-
return strdup(divenr);
}
static char *do_uemis_download(struct argument_block *args)
{
const char *mountpath = args->mountpath;
- char **xml_buffer = args->xml_buffer;
- int xml_buffer_size;
char *newmax = NULL;
- int start, end, i;
+ int start, end, i, deviceidnr;
char objectid[10];
char *deviceid = NULL;
char *result = NULL;
char *endptr;
gboolean success;
- buffer_add(xml_buffer, &xml_buffer_size, "<dives type='uemis'><string></string>\n<list>\n");
uemis_info("Init Communication");
if (! uemis_init(mountpath))
return _("Uemis init failed");
if (! uemis_get_answer(mountpath, "getDeviceId", 0, 1, &result))
goto bail;
deviceid = strdup(param_buff[0]);
+ deviceidnr = atoi(deviceid);
/* the answer from the DeviceId call becomes the input parameter for getDeviceData */
if (! uemis_get_answer(mountpath, "getDeviceData", 1, 0, &result))
goto bail;
@@ -769,35 +736,25 @@ static char *do_uemis_download(struct argument_block *args)
if (import_thread_cancelled)
goto bail;
param_buff[1] = "notempty";
- /* if we have an empty divelist then the user will almost
- * certainly want to start downloading from the first dive on
- * the Uemis; otherwise check which was the last dive
- * downloaded */
+ /* if we have an empty divelist or force it, then we start downloading from the
+ * first dive on the Uemis; otherwise check which was the last dive downloaded */
if (!args->force_download && dive_table.nr > 0)
newmax = get_divenr(deviceid);
else
newmax = strdup("0");
-
- if (sscanf(newmax, "%d", &start) != 1)
- start = 0;
+ start = atoi(newmax);
for (;;) {
param_buff[2] = newmax;
param_buff[3] = 0;
success = uemis_get_answer(mountpath, "getDivelogs", 3, 0, &result);
/* process the buffer we have assembled */
- if (mbuf) {
- char *next_seg = process_raw_buffer(mbuf, &newmax);
- buffer_add(xml_buffer, &xml_buffer_size, next_seg);
- free(next_seg);
- }
- /* if we got an error, deal with it */
- if (!success)
- break;
- /* if the user clicked cancel, exit gracefully but ignore everything read */
+ if (mbuf)
+ process_raw_buffer(deviceidnr, mbuf, &newmax);
+ /* if the user clicked cancel, exit gracefully */
if (import_thread_cancelled)
goto bail;
- /* also, if we got nothing back, we should stop trying */
- if (!param_buff[3])
+ /* if we got an error or got nothing back, stop trying */
+ if (!success || !param_buff[3])
break;
/* finally, if the memory is getting too full, maybe we better stop, too */
if (progress_bar_fraction > 0.85) {
@@ -818,16 +775,21 @@ static char *do_uemis_download(struct argument_block *args)
for (i = start; i < end; i++) {
snprintf(objectid, sizeof(objectid), "%d", i);
param_buff[2] = objectid;
- param_buff[3] = 0;
success = uemis_get_answer(mountpath, "getDive", 3, 0, &result);
- if (mbuf) {
- char *next_detail = process_raw_buffer(mbuf, &newmax);
- buffer_insert(xml_buffer, &xml_buffer_size, next_detail);
- free(next_detail);
- }
+ if (mbuf)
+ process_raw_buffer(deviceidnr, mbuf, &newmax);
if (!success || import_thread_cancelled)
break;
}
+ success = TRUE;
+ for (i = 0; i <= nr_divespots; i++) {
+ char divespotnr[10];
+ snprintf(divespotnr, sizeof(divespotnr), "%d", i);
+ param_buff[2] = divespotnr;
+ success = uemis_get_answer(mountpath, "getDivespot", 3, 0, &result);
+ if (mbuf)
+ parse_divespot(mbuf);
+ }
bail:
(void) uemis_get_answer(mountpath, "terminateSync", 0, 3, &result);
if (! strcmp(param_buff[0], "error")) {
@@ -836,13 +798,6 @@ bail:
else
result = param_buff[2];
}
- if (import_thread_cancelled)
- xml_buffer[0] = 0;
- else
- buffer_add(xml_buffer, &xml_buffer_size, "</list></dives>");
-#if UEMIS_DEBUG > 5
- fprintf(debugfile, "XML buffer \"%s\"", *xml_buffer);
-#endif
free(deviceid);
return result;
}
@@ -866,12 +821,12 @@ static gboolean timeout_func(gpointer _data)
return FALSE;
}
-GError *uemis_download(const char *mountpath, char **xml_buffer, progressbar_t *progress,
+GError *uemis_download(const char *mountpath, progressbar_t *progress,
GtkDialog *dialog, gboolean force_download)
{
pthread_t pthread;
void *retval;
- struct argument_block args = {mountpath, xml_buffer, progress, force_download};
+ struct argument_block args = {mountpath, progress, force_download};
/* I'm sure there is some better interface for waiting on a thread in a UI main loop */
import_thread_done = 0;
@@ -891,18 +846,11 @@ GError *uemis_download(const char *mountpath, char **xml_buffer, progressbar_t *
update_progressbar(args.progress, progress_bar_fraction);
update_progressbar_text(args.progress, progress_bar_text);
result = gtk_dialog_run(dialog);
- switch (result) {
- case GTK_RESPONSE_CANCEL:
+ if (result == GTK_RESPONSE_CANCEL)
import_thread_cancelled = TRUE;
- progress_bar_text = "Cancelled...";
- break;
- default:
- /* nothing */
- break;
- }
} else {
update_progressbar(args.progress, progress_bar_fraction);
- update_progressbar_text(args.progress, progress_bar_text);
+ update_progressbar_text(args.progress, "Cancelled, exiting cleanly...");
usleep(100000);
}
}
diff --git a/uemis.c b/uemis.c
index 3c5bef082..dc2e29fa8 100644
--- a/uemis.c
+++ b/uemis.c
@@ -102,6 +102,79 @@ bail:
return datalen;
}
+struct uemis_helper {
+ int diveid;
+ int lbs;
+ int divespot;
+ char **location;
+ double *latitude;
+ double *longitude;
+ struct uemis_helper *next;
+};
+static struct uemis_helper *uemis_helper = NULL;
+
+static struct uemis_helper *uemis_get_helper(int diveid)
+{
+ struct uemis_helper **php = &uemis_helper;
+ struct uemis_helper *hp = *php;
+
+ while(hp) {
+ if (hp->diveid == diveid)
+ return hp;
+ if (hp->next) {
+ hp = hp->next;
+ continue;
+ }
+ php = &hp->next;
+ break;
+ }
+ hp = *php = malloc(sizeof(struct uemis_helper));
+ hp->diveid = diveid;
+ hp->next = NULL;
+ return hp;
+}
+
+static void uemis_weight_unit(int diveid, int lbs)
+{
+ struct uemis_helper *hp = uemis_get_helper(diveid);
+ if (hp)
+ hp->lbs = lbs;
+}
+
+int uemis_get_weight_unit(int diveid)
+{
+ struct uemis_helper *hp = uemis_helper;
+ while (hp) {
+ if (hp->diveid == diveid)
+ return hp->lbs;
+ hp = hp->next;
+ }
+ /* odd - we should have found this; default to kg */
+ return 0;
+}
+
+void uemis_mark_divelocation(int diveid, int divespot, char **location, double *longitude, double *latitude)
+{
+ struct uemis_helper *hp = uemis_get_helper(diveid);
+ hp->divespot = divespot;
+ hp->location = location;
+ hp->longitude = longitude;
+ hp->latitude = latitude;
+}
+
+void uemis_set_divelocation(int divespot, char *text, double longitude, double latitude)
+{
+ struct uemis_helper *hp = uemis_helper;
+ while (hp) {
+ if (hp->divespot == divespot && hp->location) {
+ *hp->location = text;
+ *hp->longitude = longitude;
+ *hp->latitude = latitude;
+ }
+ hp = hp->next;
+ }
+}
+
/* Create events from the flag bits and other data in the sample;
* These bits basically represent what is displayed on screen at sample time.
* Many of these 'warnings' are way hyper-active and seriously clutter the
@@ -203,7 +276,9 @@ void uemis_parse_divelog_binary(char *base64, void *datap) {
dc->model = strdup("Uemis Zurich");
dc->deviceid = *(uint32_t *)(data + 9);
dc->diveid = *(uint16_t *)(data + 7);
-
+ /* remember the weight units used in this dive - we may need this later when
+ * parsing the weight */
+ uemis_weight_unit(dc->diveid, *(uint8_t *)(data + 24));
/* dive template in use:
0 = air
1 = nitrox (B)
diff --git a/uemis.h b/uemis.h
index 4cb5c2b47..9e6e0950a 100644
--- a/uemis.h
+++ b/uemis.h
@@ -8,6 +8,10 @@
#include <stdint.h>
void uemis_parse_divelog_binary(char *base64, void *divep);
+int uemis_get_weight_unit(int diveid);
+void uemis_mark_divelocation(int diveid, int divespot, char **location, double *longitude, double *latitude);
+void uemis_set_divelocation(int divespot, char *text, double longitude, double latitude);
+
void decode(uint8_t *in, uint8_t *out, int len);
typedef struct {