Parse meta information from Seaber log

This will parse date information from Seabear log file and skips the
"header" data to allow parsing of the CSV content.

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Miika Turkia 2014-10-28 11:14:00 +02:00 committed by Dirk Hohndel
parent 8da71c7d90
commit 4bc9b7748b
3 changed files with 149 additions and 52 deletions

1
dive.h
View file

@ -603,6 +603,7 @@ extern int parse_shearwater_buffer(sqlite3 *handle, const char *url, const char
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_txt_file(const char *filename, const char *csv);
extern int parse_manual_file(const char *filename, int separator_index, int units, int number, int date, int time, int duration, int location, int gps, int maxdepth, int meandepth, int buddy, int notes, int weight, int tags);

154
file.c
View file

@ -105,7 +105,7 @@ static int try_to_xslt_open_csv(const char *filename, struct memblock *mem, cons
{
char *buf;
if (readfile(filename, mem) < 0)
if (mem->size == 0 && readfile(filename, mem) < 0)
return report_error(translate("gettextFromC", "Failed to read '%s'"), filename);
/* Surround the CSV file content with XML tags to enable XSLT
@ -589,29 +589,11 @@ int parse_txt_file(const char *filename, const char *csv)
#define MAXCOLDIGITS 3
#define MAXCOLS 100
int parse_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 DATESTR 9
#define TIMESTR 6
void init_csv_file_parsing(char **params, char *timebuf, char *depthbuf, char *tempbuf, char *po2buf, char *cnsbuf, char *ndlbuf, char *ttsbuf, char *stopdepthbuf, char *pressurebuf, char *unitbuf, char *separator_index, time_t *now, struct tm *timep, char *curdate, char *curtime, 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)
{
struct memblock mem;
int pnr = 0;
char *params[27];
char timebuf[MAXCOLDIGITS];
char depthbuf[MAXCOLDIGITS];
char tempbuf[MAXCOLDIGITS];
char po2buf[MAXCOLDIGITS];
char cnsbuf[MAXCOLDIGITS];
char ndlbuf[MAXCOLDIGITS];
char ttsbuf[MAXCOLDIGITS];
char stopdepthbuf[MAXCOLDIGITS];
char pressurebuf[MAXCOLDIGITS];
char unitbuf[MAXCOLDIGITS];
char separator_index[MAXCOLDIGITS];
time_t now;
struct tm *timep;
char curdate[9];
char curtime[6];
if (timef >= MAXCOLS || depthf >= MAXCOLS || tempf >= MAXCOLS || po2f >= MAXCOLS || cnsf >= MAXCOLS || ndlf >= MAXCOLS || cnsf >= MAXCOLS || stopdepthf >= MAXCOLS || pressuref >= MAXCOLS)
return report_error(translate("gettextFromC", "Maximum number of supported columns on CSV import is %d"), MAXCOLS);
snprintf(timebuf, MAXCOLDIGITS, "%d", timef);
snprintf(depthbuf, MAXCOLDIGITS, "%d", depthf);
@ -624,13 +606,13 @@ int parse_csv_file(const char *filename, int timef, int depthf, int tempf, int p
snprintf(pressurebuf, MAXCOLDIGITS, "%d", pressuref);
snprintf(separator_index, MAXCOLDIGITS, "%d", sepidx);
snprintf(unitbuf, MAXCOLDIGITS, "%d", unitidx);
time(&now);
timep = localtime(&now);
strftime(curdate, sizeof(curdate), "%Y%m%d", timep);
time(now);
timep = localtime(now);
strftime(curdate, DATESTR, "%Y%m%d", timep);
/* As the parameter is numeric, we need to ensure that the leading zero
* is not discarded during the transform, thus prepend time with 1 */
strftime(curtime, sizeof(curtime), "1%H%M", timep);
strftime(curtime, TIMESTR, "1%H%M", timep);
params[pnr++] = "timeField";
params[pnr++] = timebuf;
@ -659,10 +641,125 @@ int parse_csv_file(const char *filename, int timef, int depthf, int tempf, int p
params[pnr++] = "separatorIndex";
params[pnr++] = separator_index;
params[pnr++] = NULL;
}
int parse_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)
{
struct memblock mem;
char *params[27];
char timebuf[MAXCOLDIGITS];
char depthbuf[MAXCOLDIGITS];
char tempbuf[MAXCOLDIGITS];
char po2buf[MAXCOLDIGITS];
char cnsbuf[MAXCOLDIGITS];
char ndlbuf[MAXCOLDIGITS];
char ttsbuf[MAXCOLDIGITS];
char stopdepthbuf[MAXCOLDIGITS];
char pressurebuf[MAXCOLDIGITS];
char unitbuf[MAXCOLDIGITS];
char separator_index[MAXCOLDIGITS];
time_t now;
struct tm *timep;
char curdate[DATESTR];
char curtime[TIMESTR];
if (timef >= MAXCOLS || depthf >= MAXCOLS || tempf >= MAXCOLS || po2f >= MAXCOLS || cnsf >= MAXCOLS || ndlf >= MAXCOLS || cnsf >= MAXCOLS || stopdepthf >= MAXCOLS || pressuref >= MAXCOLS)
return report_error(translate("gettextFromC", "Maximum number of supported columns on CSV import is %d"), MAXCOLS);
init_csv_file_parsing(params, timebuf, depthbuf, tempbuf, po2buf, cnsbuf,ndlbuf, ttsbuf, stopdepthbuf, pressurebuf, unitbuf, separator_index, &now, timep, curdate, curtime, timef, depthf, tempf, po2f, cnsf, ndlf, ttsf, stopdepthf, pressuref, sepidx, csvtemplate, unitidx);
if (filename == NULL)
return report_error("No CSV filename");
mem.size = 0;
if (try_to_xslt_open_csv(filename, &mem, csvtemplate))
return -1;
parse_xml_buffer(filename, mem.buffer, mem.size, &dive_table, (const char **)params);
free(mem.buffer);
return 0;
}
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)
{
struct memblock mem, mem_data;
char *params[27];
char timebuf[MAXCOLDIGITS];
char depthbuf[MAXCOLDIGITS];
char tempbuf[MAXCOLDIGITS];
char po2buf[MAXCOLDIGITS];
char cnsbuf[MAXCOLDIGITS];
char ndlbuf[MAXCOLDIGITS];
char ttsbuf[MAXCOLDIGITS];
char stopdepthbuf[MAXCOLDIGITS];
char pressurebuf[MAXCOLDIGITS];
char unitbuf[MAXCOLDIGITS];
char separator_index[MAXCOLDIGITS];
time_t now;
struct tm *timep;
char curdate[DATESTR];
char curtime[TIMESTR];
char *ptr, *ptr_old = NULL;
char *NL;
if (timef >= MAXCOLS || depthf >= MAXCOLS || tempf >= MAXCOLS || po2f >= MAXCOLS || cnsf >= MAXCOLS || ndlf >= MAXCOLS || cnsf >= MAXCOLS || stopdepthf >= MAXCOLS || pressuref >= MAXCOLS)
return report_error(translate("gettextFromC", "Maximum number of supported columns on CSV import is %d"), MAXCOLS);
init_csv_file_parsing(params, timebuf, depthbuf, tempbuf, po2buf, cnsbuf,ndlbuf, ttsbuf, stopdepthbuf, pressurebuf, unitbuf, separator_index, &now, timep, curdate, curtime, timef, depthf, tempf, po2f, cnsf, ndlf, ttsf, stopdepthf, pressuref, sepidx, csvtemplate, unitidx);
if (filename == NULL)
return report_error("No CSV filename");
if (readfile(filename, &mem) < 0)
return report_error(translate("gettextFromC", "Failed to read '%s'"), filename);
/* Determine NL (new line) character and the start of CSV data */
ptr = mem.buffer;
while (ptr = strstr(ptr, "\r\n\r\n")) {
ptr_old = ptr;
ptr += 1;
NL = "\r\n";
}
if (!ptr_old) {
while (ptr = strstr(ptr, "\n\n")) {
ptr_old = ptr;
ptr += 1;
}
ptr_old += 2;
NL = "\n";
} else
ptr_old += 4;
/*
* On my current sample of Seabear DC log file, the date is
* without any identifier. Thus we must search for the previous
* line and step through from there.
*/
ptr = strstr(mem.buffer, "Serial number:");
if (ptr)
ptr = strstr(ptr, NL);
/* Write date and time values to params array */
if (ptr) {
ptr += strlen(NL) + 2;
memcpy(params[19], ptr, 4);
memcpy(params[19] + 4, ptr + 5, 2);
memcpy(params[19] + 6, ptr + 8, 2);
params[19][8] = 0;
params[21][0] = '1';
memcpy(params[21] + 1, ptr + 11, 2);
memcpy(params[21] + 3, ptr + 14, 2);
params[21][5] = 0;
}
/* Move the CSV data to the start of mem buffer */
mem_data.size = (int)mem.size - (ptr_old - (char*)mem.buffer);
mem_data.buffer = ptr_old;
memmove(mem.buffer, ptr_old, mem.size - (ptr_old - (char*)mem.buffer));
mem.size = (int)mem.size - (ptr_old - (char*)mem.buffer);
if (try_to_xslt_open_csv(filename, &mem, csvtemplate))
return -1;
@ -714,11 +811,11 @@ int parse_manual_file(const char *filename, int sepidx, int units, int numberf,
snprintf(unit, MAXCOLDIGITS, "%d", units);
time(&now);
timep = localtime(&now);
strftime(curdate, sizeof(curdate), "%Y%m%d", timep);
strftime(curdate, DATESTR, "%Y%m%d", timep);
/* As the parameter is numeric, we need to ensure that the leading zero
* is not discarded during the transform, thus prepend time with 1 */
strftime(curtime, sizeof(curtime), "1%H%M", timep);
strftime(curtime, TIMESTR, "1%H%M", timep);
params[pnr++] = "numberField";
params[pnr++] = numberbuf;
@ -757,6 +854,7 @@ int parse_manual_file(const char *filename, int sepidx, int units, int numberf,
if (filename == NULL)
return report_error("No manual CSV filename");
mem.size = 0;
if (try_to_xslt_open_csv(filename, &mem, "manualCSV"))
return -1;

View file

@ -69,7 +69,8 @@ void DiveLogImportDialog::on_buttonBox_accepted()
{
if (ui->tabWidget->currentIndex() == 0) {
for (int i = 0; i < fileNames.size(); ++i) {
parse_csv_file(fileNames[i].toUtf8().data(), ui->CSVTime->value() - 1,
if (ui->knownImports->currentText() == QString("Seabear CSV")) {
parse_seabear_csv_file(fileNames[i].toUtf8().data(), ui->CSVTime->value() - 1,
ui->CSVDepth->value() - 1, VALUE_IF_CHECKED(CSVTemperature),
VALUE_IF_CHECKED(CSVpo2),
VALUE_IF_CHECKED(CSVcns),
@ -80,6 +81,26 @@ void DiveLogImportDialog::on_buttonBox_accepted()
ui->CSVSeparator->currentIndex(),
specialCSV.contains(ui->knownImports->currentIndex()) ? CSVApps[ui->knownImports->currentIndex()].name.toUtf8().data() : "csv",
ui->CSVUnits->currentIndex());
/* Seabear CSV stores NDL and TTS in Minutes, not seconds */
struct dive *dive = dive_table.dives[dive_table.nr - 1];
for(int s_nr = 0 ; s_nr <= dive->dc.samples ; s_nr++) {
struct sample *sample = dive->dc.sample + s_nr;
sample->ndl.seconds *= 60;
sample->tts.seconds *= 60;
}
} else
parse_csv_file(fileNames[i].toUtf8().data(), ui->CSVTime->value() - 1,
ui->CSVDepth->value() - 1, VALUE_IF_CHECKED(CSVTemperature),
VALUE_IF_CHECKED(CSVpo2),
VALUE_IF_CHECKED(CSVcns),
VALUE_IF_CHECKED(CSVndl),
VALUE_IF_CHECKED(CSVtts),
VALUE_IF_CHECKED(CSVstopdepth),
VALUE_IF_CHECKED(CSVpressure),
ui->CSVSeparator->currentIndex(),
specialCSV.contains(ui->knownImports->currentIndex()) ? CSVApps[ui->knownImports->currentIndex()].name.toUtf8().data() : "csv",
ui->CSVUnits->currentIndex());
}
} else {
for (int i = 0; i < fileNames.size(); ++i) {
@ -95,29 +116,6 @@ void DiveLogImportDialog::on_buttonBox_accepted()
VALUE_IF_CHECKED(Tags));
}
}
if (ui->knownImports->currentText() == QString("Seabear CSV")) {
/* Seabear CSV stores NDL and TTS in Minutes, not seconds */
struct dive *dive = dive_table.dives[dive_table.nr - 1];
for(int s_nr = 0 ; s_nr <= dive->dc.samples ; s_nr++) {
struct sample *sample = dive->dc.sample + s_nr;
sample->ndl.seconds *= 60;
sample->tts.seconds *= 60;
}
/* And the two first samples are "settings" from there software */
memmove(dive->dc.sample, dive->dc.sample + 2, sizeof(dive->dc.sample) * dive->dc.samples - 2);
dive->dc.samples -= 2;
memset(dive->dc.sample + dive->dc.samples, 0, sizeof(dive->dc.sample) * 2);
/* And fix dammanged temperature from the initial samples */
dive->mintemp.mkelvin = 0;
dive->maxtemp.mkelvin = 0;
dive->watertemp.mkelvin = 0;
dive->dc.watertemp.mkelvin = 0;
dive->cylinder[0].start.mbar = 0;
dive->cylinder[0].sample_start.mbar = 0;
fixup_dive(dive);
}
process_dives(true, false);