[PATCH 2/2] Import support for new Seabear format

Miika Turkia miika.turkia at gmail.com
Sun Mar 22 08:13:47 PDT 2015


This add support for Seabear's new import format that is used by H3 and
T1. In the future also the Hudc  should switch to the new format. The
main difference to the old one is that time stamps are no longer
recorded in the samples, but intervali is specified in the header.

The header contains other useful information as well that we should
build support for. E.g. surface pressure, gas mixes, GF, and mode might
be useful additions later on.

Signed-off-by: Miika Turkia <miika.turkia at gmail.com>
---
 dive.h                        |  2 +-
 file.c                        | 11 +++++--
 qt-ui/divelogimportdialog.cpp | 52 +++++++++++++++++++++++++++--
 qt-ui/divelogimportdialog.h   |  1 +
 xslt/csv2xml.xslt             | 76 ++++++++++++++++++++++++++++++-------------
 5 files changed, 115 insertions(+), 27 deletions(-)

diff --git a/dive.h b/dive.h
index 97d8523..86c288f 100644
--- a/dive.h
+++ b/dive.h
@@ -650,7 +650,7 @@ extern int parse_dlf_buffer(unsigned char *buffer, size_t size);
 
 extern int parse_file(const char *filename);
 extern int parse_csv_file(const char *filename, int time, int depth, int temp, int po2f, int cnsf, int ndlf, int ttsf, int stopdepthf, int pressuref, int sepidx, const char *csvtemplate, int units);
-extern int parse_seabear_csv_file(const char *filename, int time, int depth, int temp, int po2f, int cnsf, int ndlf, int ttsf, int stopdepthf, int pressuref, int sepidx, const char *csvtemplate, int units);
+extern int parse_seabear_csv_file(const char *filename, int time, int depth, int temp, int po2f, int cnsf, int ndlf, int ttsf, int stopdepthf, int pressuref, int sepidx, const char *csvtemplate, int units, const char *delta);
 extern int parse_txt_file(const char *filename, const char *csv);
 extern int parse_manual_file(const char *filename, int separator_index, int units, int dateformat, int durationformat, int number, int date, int time, int duration, int location, int gps, int maxdepth, int meandepth, int divemaster, int buddy, int notes, int weight, int tags, int cylsizef, int startpresf, int endpresf, int o2f, int hef, int airtempf, int watertempf);
 
diff --git a/file.c b/file.c
index a1871ec..4883039 100644
--- a/file.c
+++ b/file.c
@@ -908,11 +908,12 @@ int parse_csv_file(const char *filename, int timef, int depthf, int tempf, int p
 	return ret;
 }
 
-int parse_seabear_csv_file(const char *filename, int timef, int depthf, int tempf, int po2f, int cnsf, int ndlf, int ttsf, int stopdepthf, int pressuref, int sepidx, const char *csvtemplate, int unitidx)
+#define SBPARAMS 29
+int parse_seabear_csv_file(const char *filename, int timef, int depthf, int tempf, int po2f, int cnsf, int ndlf, int ttsf, int stopdepthf, int pressuref, int sepidx, const char *csvtemplate, int unitidx, const char *delta)
 {
 	int ret;
 	struct memblock mem;
-	char *params[27];
+	char *params[SBPARAMS];
 	char timebuf[MAXCOLDIGITS];
 	char depthbuf[MAXCOLDIGITS];
 	char tempbuf[MAXCOLDIGITS];
@@ -924,6 +925,7 @@ int parse_seabear_csv_file(const char *filename, int timef, int depthf, int temp
 	char pressurebuf[MAXCOLDIGITS];
 	char unitbuf[MAXCOLDIGITS];
 	char separator_index[MAXCOLDIGITS];
+	char deltabuf[MAXCOLDIGITS];
 	time_t now;
 	struct tm *timep = NULL;
 	char curdate[DATESTR];
@@ -990,6 +992,11 @@ int parse_seabear_csv_file(const char *filename, int timef, int depthf, int temp
 		params[21][5] = 0;
 	}
 
+	snprintf(deltabuf, MAXCOLDIGITS, "%s", delta);
+	params[SBPARAMS - 3] = "delta";
+	params[SBPARAMS - 2] = deltabuf;
+	params[SBPARAMS - 1] = NULL;
+
 	/* Move the CSV data to the start of mem buffer */
 	memmove(mem.buffer, ptr_old, mem.size - (ptr_old - (char*)mem.buffer));
 	mem.size = (int)mem.size - (ptr_old - (char*)mem.buffer);
diff --git a/qt-ui/divelogimportdialog.cpp b/qt-ui/divelogimportdialog.cpp
index 9697cbf..cccafda 100644
--- a/qt-ui/divelogimportdialog.cpp
+++ b/qt-ui/divelogimportdialog.cpp
@@ -316,6 +316,7 @@ DiveLogImportDialog::DiveLogImportDialog(QStringList fn, QWidget *parent) : QDia
 	ui->setupUi(this);
 	fileNames = fn;
 	column = 0;
+	delta = "0";
 
 	/* Add indexes of XSLTs requiring special handling to the list */
 	specialCSV << 3;
@@ -375,7 +376,53 @@ void DiveLogImportDialog::loadFileContents(int value, whatChanged triggeredBy)
 	QString firstLine = f.readLine();
 	if (firstLine.contains("SEABEAR")) {
 		seabear = true;
-		firstLine = "Sample time;Sample depth;Sample NDL;Sample TTS;Sample stopdepth;Sample temperature;Sample pressure";
+
+		/*
+		 * Parse header - currently only interested in sample
+		 * interval, or if we have old format (if interval value
+		 * is missing from the header).
+		 */
+
+		while ((firstLine = f.readLine()).length() > 3 && !f.atEnd()) {
+			if (firstLine.contains("//Log interval: "))
+				delta = firstLine.remove(QString::fromLatin1("//Log interval: ")).trimmed();
+		}
+
+		/*
+		 * Parse CSV fields
+		 * The pO2 values from CCR diving are ignored later on.
+		 */
+
+		firstLine = f.readLine().trimmed();
+
+		currColumns = firstLine.split(';');
+		Q_FOREACH (QString columnText, currColumns) {
+			if (columnText == "Time") {
+				headers.append("Sample time");
+			} else if (columnText == "Depth") {
+				headers.append("Sample depth");
+			} else if (columnText == "Temperature") {
+				headers.append("Sample temperature");
+			} else if (columnText == "NDT") {
+				headers.append("Sample NDL");
+			} else if (columnText == "TTS") {
+				headers.append("Sample TTS");
+			} else if (columnText == "pO2_1") {
+				headers.append("Sample pO2_1");
+			} else if (columnText == "pO2_2") {
+				headers.append("Sample pO2_2");
+			} else if (columnText == "pO2_3") {
+				headers.append("Sample pO2_3");
+			} else if (columnText == "Ceiling") {
+				headers.append("Sample ceiling");
+			} else {
+				// We do not know about this value
+				qDebug() << "Seabear import found an un-handled field: " << columnText;
+				headers.append("");
+			}
+		}
+
+		firstLine = headers.join(";");
 		blockSignals(true);
 		ui->knownImports->setCurrentText("Seabear CSV");
 		blockSignals(false);
@@ -543,7 +590,8 @@ void DiveLogImportDialog::on_buttonBox_accepted()
 						       r.indexOf(tr("Sample pressure")),
 						       ui->CSVSeparator->currentIndex(),
 						       specialCSV.contains(ui->knownImports->currentIndex()) ? CSVApps[ui->knownImports->currentIndex()].name.toUtf8().data() : "csv",
-						       ui->CSVUnits->currentIndex()
+						       ui->CSVUnits->currentIndex(),
+						       delta.toUtf8().data()
 						       ) < 0)
 					return;
 
diff --git a/qt-ui/divelogimportdialog.h b/qt-ui/divelogimportdialog.h
index 9281b2b..e7d068a 100644
--- a/qt-ui/divelogimportdialog.h
+++ b/qt-ui/divelogimportdialog.h
@@ -95,6 +95,7 @@ private:
 	QList<int> specialCSV;
 	int column;
 	ColumnNameResult *resultModel;
+	QString delta;
 
 	struct CSVAppConfig {
 		QString name;
diff --git a/xslt/csv2xml.xslt b/xslt/csv2xml.xslt
index dba2070..05f9e23 100644
--- a/xslt/csv2xml.xslt
+++ b/xslt/csv2xml.xslt
@@ -16,6 +16,7 @@
   <xsl:param name="time" select="time"/>
   <xsl:param name="units" select="units"/>
   <xsl:param name="separatorIndex" select="separatorIndex"/>
+  <xsl:param name="delta" select="delta"/>
   <xsl:output method="xml" indent="yes"/>
 
   <xsl:variable name="lf"><xsl:text>
@@ -41,6 +42,7 @@
           <divecomputerid deviceid="ffffffff" model="csv" />
           <xsl:call-template name="printLine">
             <xsl:with-param name="line" select="substring-before(//csv, $lf)"/>
+            <xsl:with-param name="lineno" select="'1'"/>
             <xsl:with-param name="remaining" select="substring-after(//csv, $lf)"/>
           </xsl:call-template>
         </dive>
@@ -50,33 +52,47 @@
 
   <xsl:template name="printLine">
     <xsl:param name="line"/>
+    <xsl:param name="lineno"/>
     <xsl:param name="remaining"/>
 
     <!-- We only want to process lines with different time stamps, and
          timeField is not necessarily the first field -->
     <xsl:if test="$line != substring-before($remaining, $lf)">
-      <xsl:variable name="curTime">
-        <xsl:call-template name="getFieldByIndex">
-          <xsl:with-param name="index" select="$timeField"/>
-          <xsl:with-param name="line" select="$line"/>
-        </xsl:call-template>
-      </xsl:variable>
-      <xsl:variable name="prevTime">
-        <xsl:call-template name="getFieldByIndex">
-          <xsl:with-param name="index" select="$timeField"/>
-          <xsl:with-param name="line" select="substring-before($remaining, $lf)"/>
-        </xsl:call-template>
-      </xsl:variable>
-
-      <xsl:if test="$curTime != $prevTime">
-        <xsl:call-template name="printFields">
-          <xsl:with-param name="line" select="$line"/>
-        </xsl:call-template>
-      </xsl:if>
+      <xsl:choose>
+        <xsl:when test="$delta != '' and $delta > 0">
+          <xsl:variable name="curTime">
+            <xsl:call-template name="getFieldByIndex">
+              <xsl:with-param name="index" select="$timeField"/>
+              <xsl:with-param name="line" select="$line"/>
+            </xsl:call-template>
+          </xsl:variable>
+          <xsl:variable name="prevTime">
+            <xsl:call-template name="getFieldByIndex">
+              <xsl:with-param name="index" select="$timeField"/>
+              <xsl:with-param name="line" select="substring-before($remaining, $lf)"/>
+            </xsl:call-template>
+          </xsl:variable>
+
+          <xsl:if test="$curTime != $prevTime">
+            <xsl:call-template name="printFields">
+              <xsl:with-param name="line" select="$line"/>
+              <xsl:with-param name="lineno" select="$lineno"/>
+            </xsl:call-template>
+          </xsl:if>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:call-template name="printFields">
+            <xsl:with-param name="line" select="$line"/>
+            <xsl:with-param name="lineno" select="'0'"/>
+          </xsl:call-template>
+        </xsl:otherwise>
+      </xsl:choose>
+
     </xsl:if>
     <xsl:if test="$remaining != ''">
       <xsl:call-template name="printLine">
         <xsl:with-param name="line" select="substring-before($remaining, $lf)"/>
+        <xsl:with-param name="lineno" select="$lineno + 1"/>
         <xsl:with-param name="remaining" select="substring-after($remaining, $lf)"/>
       </xsl:call-template>
     </xsl:if>
@@ -84,18 +100,34 @@
 
   <xsl:template name="printFields">
     <xsl:param name="line"/>
+    <xsl:param name="lineno"/>
 
     <xsl:variable name="value">
-      <xsl:call-template name="getFieldByIndex">
-        <xsl:with-param name="index" select="$timeField"/>
-        <xsl:with-param name="line" select="$line"/>
-      </xsl:call-template>
+      <xsl:choose>
+        <xsl:when test="$delta != '' and $delta > 0">
+          <xsl:value-of select="'1'"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:call-template name="getFieldByIndex">
+            <xsl:with-param name="index" select="$timeField"/>
+            <xsl:with-param name="line" select="$line"/>
+          </xsl:call-template>
+        </xsl:otherwise>
+      </xsl:choose>
     </xsl:variable>
 
+
     <xsl:if test="number($value) = $value or number(substring-before($value, ':')) = substring-before($value, ':')">
       <sample>
         <xsl:attribute name="time">
           <xsl:choose>
+            <xsl:when test="$delta != '' and $delta > 0">
+              <xsl:call-template name="sec2time">
+                <xsl:with-param name="timeSec">
+                  <xsl:value-of select="$lineno * 1"/>
+                </xsl:with-param>
+              </xsl:call-template>
+            </xsl:when>
             <xsl:when test="number($value) = $value">
               <!-- We assume time in seconds -->
 
-- 
2.1.0



More information about the subsurface mailing list