mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-27 20:58:47 +00:00
7f42acfdfb
Switch the Divesoft log file importer to use the parser in libdivecomputer. This adds support for the newer Divesoft Freedom+ log file format. Also refactor the OSTCTools log file importer to share common functionality. Signed-off-by: Michael Keller <github@ike.ch>
120 lines
3.4 KiB
C++
120 lines
3.4 KiB
C++
// SPDX-License-Identifier: GPL-2.0
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "errorhelper.h"
|
|
#include "subsurface-string.h"
|
|
#include "gettext.h"
|
|
#include "dive.h"
|
|
#include "divelist.h"
|
|
#include "divelog.h"
|
|
#include "extradata.h"
|
|
#include "file.h"
|
|
#include "format.h"
|
|
#include "libdivecomputer.h"
|
|
|
|
/*
|
|
* OSTCTools stores the raw dive data in heavily padded files, one dive
|
|
* each file. So it's not necessary to iterate once and again on a parsing
|
|
* function. Actually there's only one kind of archive for every DC model.
|
|
*/
|
|
int ostctools_import(const std::unique_ptr<std::vector<unsigned char>> &buffer, struct divelog *log)
|
|
{
|
|
if (buffer->size() < 456)
|
|
return report_error("%s", translate("gettextFromC", "Invalid OSTCTools file"));
|
|
|
|
// Read dive number from the log
|
|
auto ostcdive = std::make_unique<dive>();
|
|
ostcdive->number = (*buffer)[258] + ((*buffer)[259] << 8);
|
|
|
|
|
|
// Read device's serial number
|
|
unsigned int serial = (*buffer)[265] + ((*buffer)[266] << 8);
|
|
|
|
// Trim the buffer to the actual dive data
|
|
buffer->erase(buffer->begin(), buffer->begin() + 456);
|
|
unsigned int i = 0;
|
|
bool end_marker = false;
|
|
for (auto c: *buffer) {
|
|
i++;
|
|
if (c == 0xFD) {
|
|
if (end_marker)
|
|
break;
|
|
else
|
|
end_marker = true;
|
|
} else {
|
|
end_marker = false;
|
|
}
|
|
}
|
|
if (end_marker)
|
|
buffer->erase(buffer->begin() + i, buffer->end());
|
|
|
|
// Try to determine the dc family based on the header type
|
|
dc_family_t dc_fam;
|
|
if ((*buffer)[2] == 0x20 || (*buffer)[2] == 0x21) {
|
|
dc_fam = DC_FAMILY_HW_OSTC;
|
|
} else {
|
|
switch ((*buffer)[8]) {
|
|
case 0x22:
|
|
dc_fam = DC_FAMILY_HW_FROG;
|
|
break;
|
|
case 0x23:
|
|
case 0x24:
|
|
dc_fam = DC_FAMILY_HW_OSTC3;
|
|
break;
|
|
default:
|
|
return report_error(translate("gettextFromC", "Unknown DC in dive %d"), ostcdive->number);
|
|
}
|
|
}
|
|
|
|
// Try to determine the model based on serial number
|
|
int model;
|
|
switch (dc_fam) {
|
|
case DC_FAMILY_HW_OSTC:
|
|
if (serial > 7000)
|
|
model = 3; //2C
|
|
else if (serial > 2048)
|
|
model = 2; //2N
|
|
else if (serial > 300)
|
|
model = 1; //MK2
|
|
else
|
|
model = 0; //OSTC
|
|
break;
|
|
case DC_FAMILY_HW_FROG:
|
|
model = 0;
|
|
break;
|
|
default:
|
|
if (serial > 10000)
|
|
model = 0x12; //Sport
|
|
else
|
|
model = 0x0A; //OSTC3
|
|
}
|
|
|
|
// Prepare data to pass to libdivecomputer.
|
|
device_data_t devdata;
|
|
int ret = prepare_device_descriptor(model, dc_fam, devdata);
|
|
if (ret == 0)
|
|
return report_error(translate("gettextFromC", "Unknown DC in dive %d"), ostcdive->number);
|
|
ostcdive->dcs[0].model = devdata.vendor + " " + devdata.model + " (Imported from OSTCTools)";
|
|
|
|
// Parse the dive data
|
|
dc_status_t rc = libdc_buffer_parser(ostcdive.get(), &devdata, buffer->data(), buffer->size());
|
|
if (rc != DC_STATUS_SUCCESS)
|
|
return report_error(translate("gettextFromC", "Error - %s - parsing dive %d"), errmsg(rc), ostcdive->number);
|
|
|
|
// Serial number is not part of the header nor the profile, so libdc won't
|
|
// catch it. If Serial is part of the extra_data, and set to zero, replace it.
|
|
ostcdive->dcs[0].serial = std::to_string(serial);
|
|
|
|
auto it = find_if(ostcdive->dcs[0].extra_data.begin(), ostcdive->dcs[0].extra_data.end(),
|
|
[](auto &ed) { return ed.key == "Serial"; });
|
|
if (it != ostcdive->dcs[0].extra_data.end() && it->value == "0")
|
|
it->value = ostcdive->dcs[0].serial.c_str();
|
|
else if (it == ostcdive->dcs[0].extra_data.end())
|
|
add_extra_data(&ostcdive->dcs[0], "Serial", ostcdive->dcs[0].serial);
|
|
|
|
log->dives.record_dive(std::move(ostcdive));
|
|
|
|
return 1;
|
|
}
|