summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Miika Turkia <miika.turkia@gmail.com>2014-02-15 08:36:50 +0200
committerGravatar Dirk Hohndel <dirk@hohndel.org>2014-02-14 22:46:35 -0800
commit62e313df35df7319005b49b6011717ec0bc70088 (patch)
treebd000ecd112a9469236f819c362191ed966c2fc7
parent4b949936c26d5689c331d7c7e25b8c130e97c0e5 (diff)
downloadsubsurface-62e313df35df7319005b49b6011717ec0bc70088.tar.gz
Import Shearwater Desktop divelog database
Sqlite database from Shearwater Desktop log software is imported. Just the basic information like location, buddy, notes and dive profile (depth and temperature). This is tested with a DB in Imperial units, thus metric input might contain errors. Signed-off-by: Miika Turkia <miika.turkia@gmail.com> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r--dive.h3
-rw-r--r--file.c25
-rw-r--r--parse-xml.c104
3 files changed, 129 insertions, 3 deletions
diff --git a/dive.h b/dive.h
index 9f3df313d..e454420eb 100644
--- a/dive.h
+++ b/dive.h
@@ -644,7 +644,8 @@ extern void parse_xml_buffer(const char *url, const char *buf, int size, struct
extern void parse_xml_exit(void);
extern void set_filename(const char *filename, bool force);
-extern int parse_dm4_buffer(const sqlite3 *handle, const char *url, const char *buf, int size, struct dive_table *table, char **error);
+extern int parse_dm4_buffer(sqlite3 *handle, const char *url, const char *buf, int size, struct dive_table *table, char **error);
+extern int parse_shearwater_buffer(sqlite3 *handle, const char *url, const char *buf, int size, struct dive_table *table, char **error);
extern void parse_file(const char *filename, char **error);
extern void parse_csv_file(const char *filename, int time, int depth, int temp, int po2f, int cnsf, int stopdepthf, int sepidx, const char *csvtemplate, char **error);
diff --git a/file.c b/file.c
index b218a13e2..08b61b234 100644
--- a/file.c
+++ b/file.c
@@ -151,9 +151,17 @@ static int try_to_xslt_open_csv(const char *filename, struct memblock *mem, char
return 0;
}
+int db_test_func(void *param, int columns, char **data, char **column)
+{
+ return *data[0] == '0';
+}
+
+
static int try_to_open_db(const char *filename, struct memblock *mem, char **error)
{
sqlite3 *handle;
+ char dm4_test[] = "select count(*) from sqlite_master where type='table' and name='Dive' and sql like '%ProfileBlob%'";
+ char shearwater_test[] = "select count(*) from sqlite_master where type='table' and name='system' and sql like '%dbVersion%'";
int retval;
retval = sqlite3_open(filename, &handle);
@@ -163,7 +171,22 @@ static int try_to_open_db(const char *filename, struct memblock *mem, char **err
return 1;
}
- retval = parse_dm4_buffer(handle, filename, mem->buffer, mem->size, &dive_table, error);
+ /* Testing if DB schema resembles Suunto DM4 database format */
+ retval = sqlite3_exec(handle, dm4_test, &db_test_func, 0, NULL);
+ if (!retval) {
+ retval = parse_dm4_buffer(handle, filename, mem->buffer, mem->size, &dive_table, error);
+ sqlite3_close(handle);
+ return retval;
+ }
+
+ /* Testing if DB schema resembles Shearwater database format */
+ retval = sqlite3_exec(handle, shearwater_test, &db_test_func, 0, NULL);
+ if (!retval) {
+ retval = parse_shearwater_buffer(handle, filename, mem->buffer, mem->size, &dive_table, error);
+ sqlite3_close(handle);
+ return retval;
+ }
+
sqlite3_close(handle);
return retval;
diff --git a/parse-xml.c b/parse-xml.c
index 60a13c336..b93906f55 100644
--- a/parse-xml.c
+++ b/parse-xml.c
@@ -18,6 +18,7 @@
#include "device.h"
int verbose, quit;
+int metric = 1;
static xmlDoc *test_xslt_transforms(xmlDoc *doc, const char **params, char **error);
@@ -1861,7 +1862,7 @@ extern int dm4_dive(void *param, int columns, char **data, char **column)
return SQLITE_OK;
}
-int parse_dm4_buffer(const sqlite3 *handle, const char *url, const char *buffer, int size,
+int parse_dm4_buffer(sqlite3 *handle, const char *url, const char *buffer, int size,
struct dive_table *table, char **error)
{
int retval;
@@ -1882,6 +1883,107 @@ int parse_dm4_buffer(const sqlite3 *handle, const char *url, const char *buffer,
return 0;
}
+extern int shearwater_profile_sample(void *handle, int columns, char **data, char **column)
+{
+ sample_start();
+ if (data[0])
+ cur_sample->time.seconds = atoi(data[0]);
+ if (data[1])
+ cur_sample->depth.mm = metric ? atof(data[1]) * 1000 : feet_to_mm(atof(data[1]));
+ if (data[2])
+ cur_sample->temperature.mkelvin = metric ? C_to_mkelvin(atof(data[2])) : F_to_mkelvin(atof(data[2]));
+
+ /* We don't actually have data[3], but it should appear in the
+ * SQL query at some point.
+ if (data[3])
+ cur_sample->cylinderpressure.mbar = metric ? atoi(data[3]) * 1000 : psi_to_mbar(atoi(data[3]));
+ */
+ sample_end();
+
+ return 0;
+}
+
+extern int shearwater_dive(void *param, int columns, char **data, char **column)
+{
+ int i, interval, retval = 0;
+ sqlite3 *handle = (sqlite3 *)param;
+ float *profileBlob;
+ unsigned char *tempBlob;
+ char *err = NULL;
+ char *location, *site;
+ char get_profile_template[] = "select currentTime,currentDepth,waterTemp from dive_log_records where diveLogId = %d";
+ char get_tags_template[] = "select Text from DiveTag where DiveId = %d";
+ char get_profile_sample[128];
+
+ dive_start();
+ cur_dive->number = atoi(data[0]);
+
+ cur_dive->when = (time_t)(atol(data[1]));
+
+ if (data[2])
+ utf8_string(data[2], &cur_dive->location);
+ if (data[3])
+ utf8_string(data[3], &cur_dive->buddy);
+ if (data[4])
+ utf8_string(data[4], &cur_dive->notes);
+
+ metric = atoi(data[5]) == 1 ? 0 : 1;
+
+ /* TODO: verify that metric calculation is correct */
+ if (data[6])
+ cur_dive->dc.maxdepth.mm = metric ? atof(data[6]) * 1000 : feet_to_mm(atof(data[6]));
+
+ if (data[7])
+ cur_dive->dc.duration.seconds = atoi(data[7]) * 60;
+
+ if (data[8])
+ cur_dive->dc.surface_pressure.mbar = atoi(data[8]);
+ /*
+ * TODO: the deviceid hash should be calculated here.
+ */
+ settings_start();
+ dc_settings_start();
+ if (data[9])
+ utf8_string(data[9], &cur_settings.dc.serial_nr);
+ if (data[10])
+ utf8_string(data[10], &cur_settings.dc.model);
+
+ cur_settings.dc.deviceid = 0xffffffff;
+ dc_settings_end();
+ settings_end();
+
+ snprintf(get_profile_sample, sizeof(get_profile_sample) - 1, get_profile_template, cur_dive->number);
+ retval = sqlite3_exec(handle, get_profile_sample, &shearwater_profile_sample, 0, &err);
+ if (retval != SQLITE_OK) {
+ fprintf(stderr, "%s", translate("gettextFromC","Database query get_profile_sample failed.\n"));
+ return 1;
+ }
+
+ dive_end();
+
+ return SQLITE_OK;
+}
+
+
+int parse_shearwater_buffer(sqlite3 *handle, const char *url, const char *buffer, int size,
+ struct dive_table *table, char **error)
+{
+ int retval;
+ char *err = NULL;
+ target_table = table;
+
+ char get_dives[] = "select i.diveId,timestamp,location||' / '||site,buddy,notes,imperialUnits,maxDepth,maxTime,startSurfacePressure,computerSerial,computerModel FROM dive_info AS i JOIN dive_logs AS l ON i.diveId=l.diveId";
+
+ retval = sqlite3_exec(handle, get_dives, &shearwater_dive, handle, &err);
+
+ if (retval != SQLITE_OK) {
+ fprintf(stderr, translate("gettextFromC","Database query failed '%s'.\n"), url);
+ return 1;
+ }
+
+ return 0;
+}
+
void parse_xml_init(void)
{
LIBXML_TEST_VERSION