From 7c9b89e442e992751e23a5d223e196df17a347b6 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 9 Nov 2012 21:38:00 +0100 Subject: [PATCH 1/9] Process ceiling events and store ceiling data in plot_info This just creates the infrastructure but doesn't yet do anything useful with the data. Signed-off-by: Dirk Hohndel --- profile.c | 58 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/profile.c b/profile.c index 9b0dcb600..a4d32a78e 100644 --- a/profile.c +++ b/profile.c @@ -44,6 +44,7 @@ struct plot_info { int temperature; /* Depth info */ int depth; + int ceiling; int smoothed; double po2, pn2, phe; velocity_t velocity; @@ -185,11 +186,11 @@ static void dump_pi (struct plot_info *pi) pi->maxpressure, pi->mintemp, pi->maxtemp); for (i = 0; i < pi->nr; i++) printf(" entry[%d]:{same_cylinder:%d cylinderindex:%d sec:%d pressure:{%d,%d}\n" - " time:%d:%02d temperature:%d depth:%d smoothed:%d po2:%lf phe:%lf pn2:%lf sum-pp %lf}\n", + " time:%d:%02d temperature:%d depth:%d ceiling:%d smoothed:%d po2:%lf phe:%lf pn2:%lf sum-pp %lf}\n", i, pi->entry[i].same_cylinder, pi->entry[i].cylinderindex, pi->entry[i].sec, pi->entry[i].pressure[0], pi->entry[i].pressure[1], pi->entry[i].sec / 60, pi->entry[i].sec % 60, - pi->entry[i].temperature, pi->entry[i].depth, pi->entry[i].smoothed, + pi->entry[i].temperature, pi->entry[i].depth, pi->entry[i].ceiling, pi->entry[i].smoothed, pi->entry[i].po2, pi->entry[i].phe, pi->entry[i].pn2, pi->entry[i].po2 + pi->entry[i].phe + pi->entry[i].pn2); printf(" }\n"); @@ -294,6 +295,7 @@ static void plot_text(struct graphics_context *gc, const text_render_options_t * cairo_show_text(cr, buffer); } +/* collect all event names and whether we display them */ struct ev_select { char *ev_name; gboolean plot_ev; @@ -314,12 +316,12 @@ void evn_foreach(void (*callback)(const char *, int *, void *), void *data) void remember_event(const char *eventname) { - int i=0, len; + int i = 0, len; if (!eventname || (len = strlen(eventname)) == 0) return; while (i < evn_used) { - if (!strncmp(eventname,ev_namelist[i].ev_name,len)) + if (!strncmp(eventname, ev_namelist[i].ev_name, len)) return; i++; } @@ -1509,10 +1511,12 @@ static int get_cylinder_index(struct dive *dive, struct event *ev) return 0; } -static struct event *get_next_gaschange(struct event *event) +static struct event *get_next_event(struct event *event, char *name) { + if (!name || !*name) + return NULL; while (event) { - if (!strcmp(event->name, "gaschange")) + if (!strcmp(event->name, name)) return event; event = event->next; } @@ -1537,7 +1541,7 @@ static int set_cylinder_index(struct plot_info *pi, int i, int cylinderindex, un static void check_gas_change_events(struct dive *dive, struct plot_info *pi) { int i = 0, cylinderindex = 0; - struct event *ev = get_next_gaschange(dive->events); + struct event *ev = get_next_event(dive->events, "gaschange"); if (!ev) return; @@ -1545,7 +1549,7 @@ static void check_gas_change_events(struct dive *dive, struct plot_info *pi) do { i = set_cylinder_index(pi, i, cylinderindex, ev->time.seconds); cylinderindex = get_cylinder_index(dive, ev); - ev = get_next_gaschange(ev->next); + ev = get_next_event(ev->next, "gaschange"); } while (ev); set_cylinder_index(pi, i, cylinderindex, ~0u); } @@ -1554,11 +1558,11 @@ static void check_gas_change_events(struct dive *dive, struct plot_info *pi) static int count_gas_change_events(struct dive *dive) { int count = 0; - struct event *ev = get_next_gaschange(dive->events); + struct event *ev = get_next_event(dive->events, "gaschange"); while (ev) { count++; - ev = get_next_gaschange(ev->next); + ev = get_next_event(ev->next, "gaschange"); } return count; } @@ -1574,14 +1578,14 @@ static struct plot_info *create_plot_info(struct dive *dive, int nr_samples, str { int cylinderindex = -1; int lastdepth, lastindex; - int i, pi_idx, nr, sec, cyl; + int i, pi_idx, nr, sec, cyl, ceiling = 0; size_t alloc_size; struct plot_info *pi; pr_track_t *track_pr[MAX_CYLINDERS] = {NULL, }; pr_track_t *pr_track, *current; gboolean missing_pr = FALSE; struct plot_data *entry = NULL; - struct event *ev; + struct event *ev, *ceil_ev; /* we want to potentially add synthetic plot_info elements for the gas changes */ nr = nr_samples + 4 + 2 * count_gas_change_events(dive); @@ -1593,18 +1597,20 @@ static struct plot_info *create_plot_info(struct dive *dive, int nr_samples, str pi->nr = nr; pi_idx = 2; /* the two extra events at the start */ /* check for gas changes before the samples start */ - ev = get_next_gaschange(dive->events); + ev = get_next_event(dive->events, "gaschange"); while (ev && ev->time.seconds < dive_sample->time.seconds) { entry = pi->entry + pi_idx; entry->sec = ev->time.seconds; entry->depth = 0; /* is that always correct ? */ pi_idx++; - ev = get_next_gaschange(ev->next); + ev = get_next_event(ev->next, "gaschange"); } if (ev && ev->time.seconds == dive_sample->time.seconds) { /* we already have a sample at the time of the event */ - ev = get_next_gaschange(ev->next); + ev = get_next_event(ev->next, "gaschange"); } + /* find the first deco/ceiling event (if any) */ + ceil_ev = get_next_event(dive->events, "ceiling"); sec = 0; lastindex = 0; lastdepth = -1; @@ -1614,6 +1620,16 @@ static struct plot_info *create_plot_info(struct dive *dive, int nr_samples, str struct sample *sample = dive_sample+i; entry = pi->entry + i + pi_idx; + while (ceil_ev && ceil_ev->time.seconds <= sample->time.seconds) { + struct event *next_ceil_ev = get_next_event(dive->events, "ceiling"); + if (!next_ceil_ev || next_ceil_ev->time.seconds > sample->time.seconds) + break; + ceil_ev = next_ceil_ev; + } + if (ceil_ev && ceil_ev->time.seconds <= sample->time.seconds) { + ceiling = ceil_ev->value; + ceil_ev = get_next_event(dive->events, "ceiling"); + } while (ev && ev->time.seconds < sample->time.seconds) { /* insert two fake plot info structures for the end of * the old tank and the start of the new tank */ @@ -1630,10 +1646,12 @@ static struct plot_info *create_plot_info(struct dive *dive, int nr_samples, str (sample->depth.mm - (sample-1)->depth.mm) / 2; } else entry->depth = sample->depth.mm; - (entry+1)->depth = entry->depth; + (entry + 1)->depth = entry->depth; + entry->ceiling = ceiling; + (entry + 1)->ceiling = ceiling; pi_idx += 2; entry = pi->entry + i + pi_idx; - ev = get_next_gaschange(ev->next); + ev = get_next_event(ev->next, "gaschange"); } if (ev && ev->time.seconds == sample->time.seconds) { /* we already have a sample at the time of the event @@ -1641,13 +1659,15 @@ static struct plot_info *create_plot_info(struct dive *dive, int nr_samples, str * real even by one second (to keep time monotonous) */ entry->sec = ev->time.seconds; entry->depth = sample->depth.mm; + entry->ceiling = ceiling; pi_idx++; entry = pi->entry + i + pi_idx; - ev = get_next_gaschange(ev->next); + ev = get_next_event(ev->next, "gaschange"); delay = 1; } sec = entry->sec = sample->time.seconds + delay; depth = entry->depth = sample->depth.mm; + entry->ceiling = ceiling; entry->cylinderindex = sample->cylinderindex; SENSOR_PRESSURE(entry) = sample->cylinderpressure.mbar; entry->temperature = sample->temperature.mkelvin; @@ -1666,7 +1686,7 @@ static struct plot_info *create_plot_info(struct dive *dive, int nr_samples, str entry->depth = 0; /* why are there gas changes after the dive is over? */ pi_idx++; entry = pi->entry + i + pi_idx; - ev = get_next_gaschange(ev->next); + ev = get_next_event(ev->next, "gaschange"); } nr = nr_samples + pi_idx - 2; check_gas_change_events(dive, pi); From 6c52e8a2e51691dc256149262872c7446d7f5f38 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 9 Nov 2012 22:50:43 +0100 Subject: [PATCH 2/9] Add plotting of the deco ceiling Plot a red-shaded area on top of the depth profile to indicate the deco ceiling (i.e., the area into which it isn't save to ascend at this point of the dive. So far this is of very limited use as libdivecomputer doesn't give us the necessary information to plot this. I have sent patches for the OSTC to Jef, hoping that he will include them in an update. I don't know how many other dive computers will make this data available - I still need to add this to our native Uemis support. This commit also fixes two cut and paste errors in the previous commit 6540be9bd924 "Process ceiling events and store ceiling data in plot_info". Signed-off-by: Dirk Hohndel --- color.h | 1 + profile.c | 42 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/color.h b/color.h index eb740fbd6..38839ae7f 100644 --- a/color.h +++ b/color.h @@ -26,6 +26,7 @@ #define REDORANGE1 { 1.0, 0.2, 0.2, 1 } #define REDORANGE1_HIGH_TRANS { 1.0, 0.2, 0.2, 0.25 } #define REDORANGE1_MED_TRANS { 1.0, 0.2, 0.2, 0.5 } +#define RED1_MED_TRANS { 1.0, 0.0, 0.0, 0.5 } #define RED1 { 1.0, 0.0, 0.0, 1 } // Monochromes diff --git a/profile.c b/profile.c index a4d32a78e..c6ab46649 100644 --- a/profile.c +++ b/profile.c @@ -78,7 +78,8 @@ typedef enum { /* Other colors */ TEXT_BACKGROUND, ALERT_BG, ALERT_FG, EVENTS, SAMPLE_DEEP, SAMPLE_SHALLOW, SMOOTHED, MINUTE, TIME_GRID, TIME_TEXT, DEPTH_GRID, MEAN_DEPTH, DEPTH_TOP, - DEPTH_BOTTOM, TEMP_TEXT, TEMP_PLOT, SAC_DEFAULT, BOUNDING_BOX, PRESSURE_TEXT, BACKGROUND + DEPTH_BOTTOM, TEMP_TEXT, TEMP_PLOT, SAC_DEFAULT, BOUNDING_BOX, PRESSURE_TEXT, BACKGROUND, + CEILING_SHALLOW, CEILING_DEEP } color_indice_t; typedef struct { @@ -130,6 +131,9 @@ static const color_t profile_color[] = { [BOUNDING_BOX] = {{WHITE1, BLACK1_LOW_TRANS}}, [PRESSURE_TEXT] = {{KILLARNEY1, BLACK1_LOW_TRANS}}, [BACKGROUND] = {{SPRINGWOOD1, BLACK1_LOW_TRANS}}, + [CEILING_SHALLOW] = {{REDORANGE1_HIGH_TRANS, REDORANGE1_HIGH_TRANS}}, + [CEILING_DEEP] = {{RED1_MED_TRANS, RED1_MED_TRANS}}, + }; #define plot_info_size(nr) (sizeof(struct plot_info) + (nr)*sizeof(struct plot_data)) @@ -839,6 +843,7 @@ static void plot_depth_profile(struct graphics_context *gc, struct plot_info *pi struct plot_data *entry; int maxtime, maxdepth, marker; int increments[8] = { 10, 20, 30, 60, 5*60, 10*60, 15*60, 30*60 }; + gboolean plotting = FALSE; /* Get plot scaling limits */ maxtime = get_maxtime(pi); @@ -948,6 +953,36 @@ static void plot_depth_profile(struct graphics_context *gc, struct plot_info *pi line_to(gc, sec, depth); cairo_stroke(cr); } + + /* now on top of this the ceiling plot */ + entry = pi->entry; + pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, 256.0 * plot_scale); + pattern_add_color_stop_rgba (gc, pat, 0.5, CEILING_DEEP); + pattern_add_color_stop_rgba (gc, pat, 0, CEILING_SHALLOW); + cairo_set_source(gc->cr, pat); + cairo_pattern_destroy(pat); + cairo_set_line_width_scaled(gc->cr, 2); + for (i = 0; i < pi->nr; i++, entry++) { + if (entry->ceiling > 0) { + if (!plotting) { + move_to(gc, entry->sec, 0); + plotting = TRUE; + } + line_to(gc, entry->sec, entry->ceiling); + } else { + if (plotting) { + line_to(gc, entry->sec, 0); + cairo_close_path(gc->cr); + cairo_fill(gc->cr); + plotting = FALSE; + } + } + } + if (plotting) { + line_to(gc, entry->sec, 0); + cairo_close_path(gc->cr); + cairo_fill(gc->cr); + } } static int setup_temperature_limits(struct graphics_context *gc, struct plot_info *pi) @@ -1621,14 +1656,14 @@ static struct plot_info *create_plot_info(struct dive *dive, int nr_samples, str entry = pi->entry + i + pi_idx; while (ceil_ev && ceil_ev->time.seconds <= sample->time.seconds) { - struct event *next_ceil_ev = get_next_event(dive->events, "ceiling"); + struct event *next_ceil_ev = get_next_event(ceil_ev->next, "ceiling"); if (!next_ceil_ev || next_ceil_ev->time.seconds > sample->time.seconds) break; ceil_ev = next_ceil_ev; } if (ceil_ev && ceil_ev->time.seconds <= sample->time.seconds) { ceiling = ceil_ev->value; - ceil_ev = get_next_event(dive->events, "ceiling"); + ceil_ev = get_next_event(ceil_ev->next, "ceiling"); } while (ev && ev->time.seconds < sample->time.seconds) { /* insert two fake plot info structures for the end of @@ -1636,7 +1671,6 @@ static struct plot_info *create_plot_info(struct dive *dive, int nr_samples, str if (ev->time.seconds == sample->time.seconds - 1) { entry->sec = ev->time.seconds - 1; (entry+1)->sec = ev->time.seconds; - } else { entry->sec = ev->time.seconds; (entry+1)->sec = ev->time.seconds + 1; } From 097702a39216311b2f2e32d56f66318ba9f0d34a Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 9 Nov 2012 23:00:54 +0100 Subject: [PATCH 3/9] Ignore last dive read from Uemis when starting with empty divelist When the user closes the divelist and starts with an empty file it makes no sense to assume that she only wants to download new dives since the last time dives have been downloaded. So if the current divelist is empty we ignore that information and start from the beginning again. Signed-off-by: Dirk Hohndel --- uemis-downloader.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/uemis-downloader.c b/uemis-downloader.c index 5267a0b00..6f85eca59 100644 --- a/uemis-downloader.c +++ b/uemis-downloader.c @@ -792,7 +792,15 @@ static char *do_uemis_download(struct argument_block *args) if (! uemis_get_answer(mountpath, "processSync", 0, 2, &result)) goto bail; param_buff[1] = "notempty"; - newmax = get_divenr(*max_dive_data, deviceid); + /* 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 (dive_table.nr > 0) + newmax = get_divenr(*max_dive_data, deviceid); + else + newmax = strdup("0"); + if (sscanf(newmax, "%d", &start) != 1) start = 0; for (;;) { From 7db08ae1283bab866931fef8f9820366e6b66b5d Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 10 Nov 2012 09:23:19 +0100 Subject: [PATCH 4/9] Instead of the ugly red boxes make the surface come down to ceiling Based on suggestions from Linus (and a few iterations) we now simply have the surface (i.e., background color / pattern) come down to where the ceiling is. And we only do the angry red shading when the diver violates the ceiling. I think this looks much better. Signed-off-by: Dirk Hohndel --- profile.c | 62 +++++++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/profile.c b/profile.c index c6ab46649..e20527986 100644 --- a/profile.c +++ b/profile.c @@ -843,7 +843,6 @@ static void plot_depth_profile(struct graphics_context *gc, struct plot_info *pi struct plot_data *entry; int maxtime, maxdepth, marker; int increments[8] = { 10, 20, 30, 60, 5*60, 10*60, 15*60, 30*60 }; - gboolean plotting = FALSE; /* Get plot scaling limits */ maxtime = get_maxtime(pi); @@ -935,8 +934,37 @@ static void plot_depth_profile(struct graphics_context *gc, struct plot_info *pi move_to(gc, 0, 0); for (i = 0; i < pi->nr; i++, entry++) line_to(gc, entry->sec, entry->depth); - cairo_close_path(gc->cr); + /* Show any ceiling we may have encountered */ + for (i = pi->nr - 1; i >= 0; i--, entry--) { + if (entry->ceiling < entry->depth) { + line_to(gc, entry->sec, entry->ceiling); + } else { + line_to(gc, entry->sec, entry->depth); + } + } + cairo_close_path(gc->cr); + cairo_fill(gc->cr); + + /* next show where we have been bad and crossed the ceiling */ + pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, 256.0 * plot_scale); + pattern_add_color_stop_rgba (gc, pat, 0, CEILING_SHALLOW); + pattern_add_color_stop_rgba (gc, pat, 1, CEILING_DEEP); + cairo_set_source(gc->cr, pat); + cairo_pattern_destroy(pat); + entry = pi->entry; + move_to(gc, 0, 0); + for (i = 0; i < pi->nr; i++, entry++) + line_to(gc, entry->sec, entry->depth); + + for (i = pi->nr - 1; i >= 0; i--, entry--) { + if (entry->ceiling > entry->depth) { + line_to(gc, entry->sec, entry->ceiling); + } else { + line_to(gc, entry->sec, entry->depth); + } + } + cairo_close_path(gc->cr); cairo_fill(gc->cr); /* Now do it again for the velocity colors */ @@ -953,36 +981,6 @@ static void plot_depth_profile(struct graphics_context *gc, struct plot_info *pi line_to(gc, sec, depth); cairo_stroke(cr); } - - /* now on top of this the ceiling plot */ - entry = pi->entry; - pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, 256.0 * plot_scale); - pattern_add_color_stop_rgba (gc, pat, 0.5, CEILING_DEEP); - pattern_add_color_stop_rgba (gc, pat, 0, CEILING_SHALLOW); - cairo_set_source(gc->cr, pat); - cairo_pattern_destroy(pat); - cairo_set_line_width_scaled(gc->cr, 2); - for (i = 0; i < pi->nr; i++, entry++) { - if (entry->ceiling > 0) { - if (!plotting) { - move_to(gc, entry->sec, 0); - plotting = TRUE; - } - line_to(gc, entry->sec, entry->ceiling); - } else { - if (plotting) { - line_to(gc, entry->sec, 0); - cairo_close_path(gc->cr); - cairo_fill(gc->cr); - plotting = FALSE; - } - } - } - if (plotting) { - line_to(gc, entry->sec, 0); - cairo_close_path(gc->cr); - cairo_fill(gc->cr); - } } static int setup_temperature_limits(struct graphics_context *gc, struct plot_info *pi) From 4da31687688da9f89a5ef6288ea8920736f2ec1b Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 10 Nov 2012 09:28:02 +0100 Subject: [PATCH 5/9] Create the correct ceiling events for Uemis Zurich The hold_depth field is rather misleading as it normally gives the safety stop depth and only when the p_amb_tol goes "below the surface" does it switch to showing the first deco stop depth. Signed-off-by: Dirk Hohndel --- Makefile | 2 +- uemis.c | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 448cff807..90403c4f1 100644 --- a/Makefile +++ b/Makefile @@ -252,7 +252,7 @@ gtk-gui.o: gtk-gui.c dive.h display.h divelist.h display-gtk.h libdivecomputer.h -c gtk-gui.c uemis.o: uemis.c dive.h uemis.h - $(CC) $(CFLAGS) $(GTK2CFLAGS) $(GLIB2CFLAGS) $(XML2CFLAGS) -c uemis.c + $(CC) $(CFLAGS) $(GTK2CFLAGS) $(GLIB2CFLAGS) $(XML2CFLAGS) $(LIBDIVECOMPUTERCFLAGS) -c uemis.c uemis-downloader.o: uemis-downloader.c dive.h uemis.h $(CC) $(CFLAGS) $(GTK2CFLAGS) $(GLIB2CFLAGS) $(XML2CFLAGS) -c uemis-downloader.c diff --git a/uemis.c b/uemis.c index 25ff9bf49..8758b7f38 100644 --- a/uemis.c +++ b/uemis.c @@ -18,6 +18,7 @@ #include "dive.h" #include "uemis.h" +#include /* * following code is based on code found in at base64.sourceforge.net/b64.c @@ -119,7 +120,9 @@ bail: return datalen; } -/* Create events from the flag bits; +static gboolean in_deco; + +/* 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 * profile plot - so these are disabled by default @@ -175,6 +178,19 @@ void uemis_event(struct dive *dive, struct sample *sample, uemis_sample_t *u_sam add_event(dive, sample->time.seconds, 0, 0, 0, N_("Low Battery Alert")); /* flags[7] reflects the little on screen icons that remind of previous * warnings / alerts - not useful for events */ + + /* now add deco / ceiling events */ + if (u_sample->p_amb_tol > 1013 && u_sample->hold_time && u_sample->hold_time < 99) { + add_event(dive, sample->time.seconds, SAMPLE_EVENT_CEILING, SAMPLE_FLAGS_BEGIN, + u_sample->hold_depth * 10, N_("ceiling")); + add_event(dive, sample->time.seconds, SAMPLE_EVENT_DECOSTOP, 0, + u_sample->hold_time, N_("deco")); + in_deco = TRUE; + } else if (in_deco) { + in_deco = FALSE; + add_event(dive, sample->time.seconds, SAMPLE_EVENT_CEILING, SAMPLE_FLAGS_END, + 0, N_("ceiling")); + } } /* @@ -190,6 +206,7 @@ void uemis_parse_divelog_binary(char *base64, void *datap) { struct dive *dive = *divep; int template, gasoffset; + in_deco = FALSE; datalen = uemis_convert_base64(base64, &data); dive->airtemp.mkelvin = *(uint16_t *)(data + 45) * 100 + 273150; From cc53a0cf5c4748853884eb92b100f0e406b015ae Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 10 Nov 2012 09:37:23 +0100 Subject: [PATCH 6/9] Use correct surface pressure to detect ceiling with Uemis Zurich The dive data contains the surface pressure prior to the dive, and that is what we need to compare p_amb_tol to, not the standard 1013mbar. Signed-off-by: Dirk Hohndel --- dive.h | 1 + uemis.c | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/dive.h b/dive.h index d9f587a79..114ab9cbf 100644 --- a/dive.h +++ b/dive.h @@ -269,6 +269,7 @@ struct dive { duration_t duration, surfacetime; int visibility; /* 0 - 5 star rating */ temperature_t airtemp, watertemp; + pressure_t surface_pressure; cylinder_t cylinder[MAX_CYLINDERS]; weightsystem_t weightsystem[MAX_WEIGHTSYSTEMS]; char *suit; diff --git a/uemis.c b/uemis.c index 8758b7f38..c12b53c8e 100644 --- a/uemis.c +++ b/uemis.c @@ -180,7 +180,9 @@ void uemis_event(struct dive *dive, struct sample *sample, uemis_sample_t *u_sam * warnings / alerts - not useful for events */ /* now add deco / ceiling events */ - if (u_sample->p_amb_tol > 1013 && u_sample->hold_time && u_sample->hold_time < 99) { + if (u_sample->p_amb_tol > dive->surface_pressure.mbar && + u_sample->hold_time && + u_sample->hold_time < 99) { add_event(dive, sample->time.seconds, SAMPLE_EVENT_CEILING, SAMPLE_FLAGS_BEGIN, u_sample->hold_depth * 10, N_("ceiling")); add_event(dive, sample->time.seconds, SAMPLE_EVENT_DECOSTOP, 0, @@ -210,7 +212,7 @@ void uemis_parse_divelog_binary(char *base64, void *datap) { datalen = uemis_convert_base64(base64, &data); dive->airtemp.mkelvin = *(uint16_t *)(data + 45) * 100 + 273150; - + dive->surface_pressure.mbar = *(uint16_t *)(data +43); /* dive template in use: 0 = air 1 = nitrox (B) From 7b1867487186bbc80a8355ecbceb001943cac976 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 10 Nov 2012 09:59:20 +0100 Subject: [PATCH 7/9] Fix cut and paste error in an error message This has been around for a loooong time, I just happened to stamble across it when reading the code... Signed-off-by: Dirk Hohndel --- parse-xml.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parse-xml.c b/parse-xml.c index 9429580e6..272b82c0f 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -545,7 +545,7 @@ static void decicelsius(char *buffer, void *_temp) temp->mkelvin = (val.fp/10 + 273.15) * 1000 + 0.5; break; default: - fprintf(stderr, "Strange julian date: %s", buffer); + fprintf(stderr, "Strange temperature: %s", buffer); } free(buffer); } From e07531dd10a9126544b4cb949b05ee2d15a50d5d Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 10 Nov 2012 11:36:59 +0100 Subject: [PATCH 8/9] Convert Uemis deco stop hold time to seconds This is actually stored in minutes (which seems odd, given they allocate 16 bits for it... how much deco do these people want to be prepared for??) Signed-off-by: Dirk Hohndel --- uemis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uemis.c b/uemis.c index c12b53c8e..72d20e360 100644 --- a/uemis.c +++ b/uemis.c @@ -186,7 +186,7 @@ void uemis_event(struct dive *dive, struct sample *sample, uemis_sample_t *u_sam add_event(dive, sample->time.seconds, SAMPLE_EVENT_CEILING, SAMPLE_FLAGS_BEGIN, u_sample->hold_depth * 10, N_("ceiling")); add_event(dive, sample->time.seconds, SAMPLE_EVENT_DECOSTOP, 0, - u_sample->hold_time, N_("deco")); + u_sample->hold_time * 60, N_("deco")); in_deco = TRUE; } else if (in_deco) { in_deco = FALSE; From 6ad73a8f043be283c07df34c6a5a43fee1b444e8 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 10 Nov 2012 11:40:35 +0100 Subject: [PATCH 9/9] Improve logic handling events We now throw away redundant events, just as we throw away other redundant data coming from the dive computer. Events are considered redundant if they are less than 61 seconds apart and identical. This also improves the display of the remaining events in the profile as we now show the value of the event, if it is present (for example for a deco event we show the duration of the deepest stop). Finally, for events that define a range (so they set the beginning flag and assume and end flag some time later) we no loger show the triangle but assume that some other code handles visualizing them (as happens for the ceiling events). Signed-off-by: Dirk Hohndel --- dive.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ dive.h | 1 + gtk-gui.c | 2 +- profile.c | 11 ++++++++-- 4 files changed, 72 insertions(+), 3 deletions(-) diff --git a/dive.c b/dive.c index c855acef8..06d15efdd 100644 --- a/dive.c +++ b/dive.c @@ -373,6 +373,30 @@ static void sanitize_cylinder_info(struct dive *dive) } } +/* some events should never be thrown away */ +static gboolean is_potentially_redundant(struct event *event) +{ + if (!strcmp(event->name, "gaschange")) + return FALSE; + return TRUE; +} + +/* match just by name - we compare the details in the code that uses this helper */ +static struct event *find_previous_event(struct dive *dive, struct event *event) +{ + struct event *ev = dive->events; + struct event *previous = NULL; + + if (!event->name) + return NULL; + while (ev && ev != event) { + if(ev->name && !strcmp(ev->name, event->name)) + previous = ev; + ev = ev->next; + } + return previous; +} + struct dive *fixup_dive(struct dive *dive) { int i,j; @@ -384,6 +408,7 @@ struct dive *fixup_dive(struct dive *dive) int lastdepth = 0; int lasttemp = 0, lastpressure = 0; int pressure_delta[MAX_CYLINDERS] = {INT_MAX, }; + struct event *event; add_people(dive->buddy); add_people(dive->divemaster); @@ -514,6 +539,42 @@ struct dive *fixup_dive(struct dive *dive) add_weightsystem_description(ws); } + /* events are stored as a linked list, so the concept of + * "consecutive, identical events" is somewhat hard to + * implement correctly (especially given that on some dive + * computers events are asynchronous, so they can come in + * between what would be the non-constant sample rate). + * + * So what we do is that we throw away clearly redundant + * events that are fewer than 61 seconds apart (assuming there + * is no dive computer with a sample rate of more than 60 + * seconds... that would be pretty pointless to plot the + * profile with) + * We first only mark the events for deletion so that we + * still know when the previous event happened. */ + event = dive->events; + while (event) { + struct event *prev; + if (is_potentially_redundant(event)) { + prev = find_previous_event(dive, event); + if (prev && prev->value == event->value && + prev->flags == event->flags && + event->time.seconds - prev->time.seconds < 61) + event->deleted = TRUE; + } + event = event->next; + } + event = dive->events; + while (event) { + if (event->next && event->next->deleted) { + struct event *nextnext = event->next->next; + free(event->next); + event->next = nextnext; + } else { + event = event->next; + } + } + return dive; } diff --git a/dive.h b/dive.h index 114ab9cbf..a6ba61519 100644 --- a/dive.h +++ b/dive.h @@ -233,6 +233,7 @@ struct event { struct event *next; duration_t time; int type, flags, value; + gboolean deleted; char name[]; }; diff --git a/gtk-gui.c b/gtk-gui.c index 665a4abef..690b2a488 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -1231,7 +1231,7 @@ void attach_tooltip(int x, int y, int w, int h, const char *text) rect->y = y; rect->width = w; rect->height = h; - tooltip_rects[tooltips].text = text; + tooltip_rects[tooltips].text = strdup(text); tooltips++; } diff --git a/profile.c b/profile.c index e20527986..7902560f3 100644 --- a/profile.c +++ b/profile.c @@ -15,6 +15,7 @@ #include "display-gtk.h" #include "divelist.h" #include "color.h" +#include "libdivecomputer/parser.h" int selected_dive = 0; char zoomed_plot = 0; @@ -345,6 +346,7 @@ static void plot_one_event(struct graphics_context *gc, struct plot_info *pi, st { int i, depth = 0; int x,y; + char buffer[80]; /* is plotting this event disabled? */ if (event->name) { @@ -380,7 +382,11 @@ static void plot_one_event(struct graphics_context *gc, struct plot_info *pi, st cairo_line_to(gc->cr, x-9, y+4); cairo_stroke(gc->cr); /* we display the event on screen - so translate */ - attach_tooltip(x-15, y-6, 12, 12, _(event->name)); + if (event->value) + snprintf(buffer, sizeof(buffer), "%s: %d", _(event->name), event->value); + else + snprintf(buffer, sizeof(buffer), "%s", _(event->name)); + attach_tooltip(x-15, y-6, 12, 12, buffer); } static void plot_events(struct graphics_context *gc, struct plot_info *pi, struct dive *dive) @@ -392,7 +398,8 @@ static void plot_events(struct graphics_context *gc, struct plot_info *pi, struc return; while (event) { - plot_one_event(gc, pi, event, &tro); + if (event->flags != SAMPLE_FLAGS_BEGIN && event->flags != SAMPLE_FLAGS_END) + plot_one_event(gc, pi, event, &tro); event = event->next; } }