mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Import: Add Parsing for Divesoft Freedom+ Format Files.
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>
This commit is contained in:
parent
7dc92e170f
commit
7f42acfdfb
10 changed files with 153 additions and 588 deletions
|
@ -1770,499 +1770,6 @@ int parse_xml_buffer(const char *url, const char *buffer, int, struct divelog *l
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a unsigned 32-bit integer in little-endian mode,
|
||||
* that is seconds since Jan 1, 2000.
|
||||
*/
|
||||
static timestamp_t parse_dlf_timestamp(unsigned char *buffer)
|
||||
{
|
||||
timestamp_t offset;
|
||||
|
||||
offset = buffer[3];
|
||||
offset = (offset << 8) + buffer[2];
|
||||
offset = (offset << 8) + buffer[1];
|
||||
offset = (offset << 8) + buffer[0];
|
||||
|
||||
// Jan 1, 2000 is 946684800 seconds after Jan 1, 1970, which is
|
||||
// the Unix epoch date that "timestamp_t" uses.
|
||||
return offset + 946684800;
|
||||
}
|
||||
|
||||
int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divelog *log)
|
||||
{
|
||||
using namespace std::string_literals;
|
||||
unsigned char *ptr = buffer;
|
||||
unsigned char event;
|
||||
bool found;
|
||||
unsigned int time = 0;
|
||||
char serial[6];
|
||||
struct battery_status {
|
||||
uint16_t volt1;
|
||||
uint8_t percent1;
|
||||
uint16_t volt2;
|
||||
uint8_t percent2;
|
||||
};
|
||||
struct battery_status battery_start = {0, 0, 0, 0};
|
||||
struct battery_status battery_end = {0, 0, 0, 0};
|
||||
uint16_t o2_sensor_calibration_values[4] = {0};
|
||||
cylinder_t *cyl;
|
||||
struct parser_state state;
|
||||
|
||||
state.log = log;
|
||||
|
||||
// Check for the correct file magic
|
||||
if (ptr[0] != 'D' || ptr[1] != 'i' || ptr[2] != 'v' || ptr[3] != 'E')
|
||||
return -1;
|
||||
|
||||
dive_start(&state);
|
||||
divecomputer_start(&state);
|
||||
|
||||
state.cur_dc->model = "DLF import";
|
||||
// (ptr[7] << 8) + ptr[6] Is "Serial"
|
||||
snprintf(serial, sizeof(serial), "%d", (ptr[7] << 8) + ptr[6]);
|
||||
state.cur_dc->serial = serial;
|
||||
state.cur_dc->when = parse_dlf_timestamp(ptr + 8);
|
||||
state.cur_dive->when = state.cur_dc->when;
|
||||
|
||||
state.cur_dc->duration.seconds = ((ptr[14] & 0xFE) << 16) + (ptr[13] << 8) + ptr[12];
|
||||
|
||||
// ptr[14] >> 1 is scrubber used in %
|
||||
|
||||
// 3 bit dive type
|
||||
switch((ptr[15] & 0x38) >> 3) {
|
||||
case 0: // unknown
|
||||
case 1:
|
||||
state.cur_dc->divemode = OC;
|
||||
break;
|
||||
case 2:
|
||||
state.cur_dc->divemode = CCR;
|
||||
break;
|
||||
case 3:
|
||||
state.cur_dc->divemode = CCR; // mCCR
|
||||
break;
|
||||
case 4:
|
||||
state.cur_dc->divemode = FREEDIVE;
|
||||
break;
|
||||
case 5:
|
||||
state.cur_dc->divemode = OC; // Gauge
|
||||
break;
|
||||
case 6:
|
||||
state.cur_dc->divemode = PSCR; // ASCR
|
||||
break;
|
||||
case 7:
|
||||
state.cur_dc->divemode = PSCR;
|
||||
break;
|
||||
}
|
||||
|
||||
state.cur_dc->maxdepth.mm = ((ptr[21] << 8) + ptr[20]) * 10;
|
||||
state.cur_dc->surface_pressure.mbar = ((ptr[25] << 8) + ptr[24]) / 10;
|
||||
|
||||
// Declare initial mix as first cylinder
|
||||
cyl = state.cur_dive->get_or_create_cylinder(0);
|
||||
cyl->gasmix.o2.permille = ptr[26] * 10;
|
||||
cyl->gasmix.he.permille = ptr[27] * 10;
|
||||
|
||||
/* Done with parsing what we know about the dive header */
|
||||
ptr += 32;
|
||||
|
||||
// We're going to interpret ppO2 saved as a sensor value in these modes.
|
||||
if (state.cur_dc->divemode == CCR || state.cur_dc->divemode == PSCR)
|
||||
state.cur_dc->no_o2sensors = 1;
|
||||
|
||||
for (; ptr < buffer + size; ptr += 16) {
|
||||
time = ((ptr[0] >> 4) & 0x0f) +
|
||||
((ptr[1] << 4) & 0xff0) +
|
||||
((ptr[2] << 12) & 0x1f000);
|
||||
event = ptr[0] & 0x0f;
|
||||
switch (event) {
|
||||
case 0:
|
||||
/* Regular sample */
|
||||
sample_start(&state);
|
||||
state.cur_sample->time.seconds = time;
|
||||
state.cur_sample->depth.mm = ((ptr[5] << 8) + ptr[4]) * 10;
|
||||
// Crazy precision on these stored values...
|
||||
// Only store value if we're in CCR/PSCR mode,
|
||||
// because we rather calculate ppo2 our selfs.
|
||||
if (state.cur_dc->divemode == CCR || state.cur_dc->divemode == PSCR)
|
||||
state.cur_sample->o2sensor[0].mbar = ((ptr[7] << 8) + ptr[6]) / 10;
|
||||
|
||||
// In some test files, ndl / tts / temp is bogus if this bits are 1
|
||||
// flag bits in ptr[11] & 0xF0 is probably involved to,
|
||||
if ((ptr[2] >> 5) != 1) {
|
||||
// NDL in minutes, 10 bit
|
||||
state.cur_sample->ndl.seconds = (((ptr[9] & 0x03) << 8) + ptr[8]) * 60;
|
||||
// TTS in minutes, 10 bit
|
||||
state.cur_sample->tts.seconds = (((ptr[10] & 0x0F) << 6) + (ptr[9] >> 2)) * 60;
|
||||
// Temperature in 1/10 C, 10 bit signed
|
||||
state.cur_sample->temperature.mkelvin = ((ptr[11] & 0x20) ? -1 : 1) * (((ptr[11] & 0x1F) << 4) + (ptr[10] >> 4)) * 100 + ZERO_C_IN_MKELVIN;
|
||||
}
|
||||
state.cur_sample->stopdepth.mm = ((ptr[13] << 8) + ptr[12]) * 10;
|
||||
if (state.cur_sample->stopdepth.mm)
|
||||
state.cur_sample->in_deco = true;
|
||||
//ptr[14] is helium content, always zero?
|
||||
//ptr[15] is setpoint, what the computer thinks you should aim for?
|
||||
sample_end(&state);
|
||||
break;
|
||||
case 1: /* dive event */
|
||||
case 2: /* automatic parameter change */
|
||||
case 3: /* diver error */
|
||||
case 4: /* internal error */
|
||||
case 5: /* device activity log */
|
||||
//Event 18 is a button press. Lets ingore that event.
|
||||
if (ptr[4] == 18)
|
||||
continue;
|
||||
|
||||
event_start(&state);
|
||||
state.cur_event.time.seconds = time;
|
||||
switch (ptr[4]) {
|
||||
case 1:
|
||||
state.cur_event.name = "Setpoint Manual"s;
|
||||
state.cur_event.value = ptr[6];
|
||||
sample_start(&state);
|
||||
state.cur_sample->setpoint.mbar = ptr[6] * 10;
|
||||
sample_end(&state);
|
||||
break;
|
||||
case 2:
|
||||
state.cur_event.name = "Setpoint Auto"s;
|
||||
state.cur_event.value = ptr[6];
|
||||
sample_start(&state);
|
||||
state.cur_sample->setpoint.mbar = ptr[6] * 10;
|
||||
sample_end(&state);
|
||||
switch (ptr[7]) {
|
||||
case 0:
|
||||
state.cur_event.name += " Manual"s;
|
||||
break;
|
||||
case 1:
|
||||
state.cur_event.name += " Auto Start"s;
|
||||
break;
|
||||
case 2:
|
||||
state.cur_event.name += " Auto Hypox"s;
|
||||
break;
|
||||
case 3:
|
||||
state.cur_event.name += " Auto Timeout"s;
|
||||
break;
|
||||
case 4:
|
||||
state.cur_event.name += " Auto Ascent"s;
|
||||
break;
|
||||
case 5:
|
||||
state.cur_event.name += " Auto Stall"s;
|
||||
break;
|
||||
case 6:
|
||||
state.cur_event.name += " Auto SP Low"s;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
// obsolete
|
||||
state.cur_event.name = "OC"s;
|
||||
break;
|
||||
case 4:
|
||||
// obsolete
|
||||
state.cur_event.name = "CCR"s;
|
||||
break;
|
||||
case 5:
|
||||
state.cur_event.name = "gaschange"s;
|
||||
state.cur_event.type = SAMPLE_EVENT_GASCHANGE2;
|
||||
state.cur_event.value = ptr[7] << 8 ^ ptr[6];
|
||||
|
||||
for (const auto [i, cyl]: enumerated_range(state.cur_dive->cylinders)) {
|
||||
if (cyl.gasmix.o2.permille == ptr[6] * 10 && cyl.gasmix.he.permille == ptr[7] * 10) {
|
||||
found = true;
|
||||
state.cur_event.gas.index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
cyl = cylinder_start(&state);
|
||||
cyl->gasmix.o2.permille = ptr[6] * 10;
|
||||
cyl->gasmix.he.permille = ptr[7] * 10;
|
||||
cylinder_end(&state);
|
||||
state.cur_event.gas.index = static_cast<int>(state.cur_dive->cylinders.size()) - 1;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
state.cur_event.name = "Start"s;
|
||||
break;
|
||||
case 7:
|
||||
state.cur_event.name = "Too Fast"s;
|
||||
break;
|
||||
case 8:
|
||||
state.cur_event.name = "Above Ceiling"s;
|
||||
break;
|
||||
case 9:
|
||||
state.cur_event.name = "Toxic"s;
|
||||
break;
|
||||
case 10:
|
||||
state.cur_event.name = "Hypox"s;
|
||||
break;
|
||||
case 11:
|
||||
state.cur_event.name = "Critical"s;
|
||||
break;
|
||||
case 12:
|
||||
state.cur_event.name = "Sensor Disabled"s;
|
||||
break;
|
||||
case 13:
|
||||
state.cur_event.name = "Sensor Enabled"s;
|
||||
break;
|
||||
case 14:
|
||||
state.cur_event.name = "O2 Backup"s;
|
||||
break;
|
||||
case 15:
|
||||
state.cur_event.name = "Peer Down"s;
|
||||
break;
|
||||
case 16:
|
||||
state.cur_event.name = "HS Down"s;
|
||||
break;
|
||||
case 17:
|
||||
state.cur_event.name = "Inconsistent"s;
|
||||
break;
|
||||
case 18:
|
||||
// key pressed - It should never get in here
|
||||
// as we ingored it at the parent 'case 5'.
|
||||
break;
|
||||
case 19:
|
||||
// obsolete
|
||||
state.cur_event.name = "SCR"s;
|
||||
break;
|
||||
case 20:
|
||||
state.cur_event.name = "Above Stop"s;
|
||||
break;
|
||||
case 21:
|
||||
state.cur_event.name = "Safety Miss"s;
|
||||
break;
|
||||
case 22:
|
||||
state.cur_event.name = "Fatal"s;
|
||||
break;
|
||||
case 23:
|
||||
state.cur_event.name = "gaschange"s;
|
||||
state.cur_event.type = SAMPLE_EVENT_GASCHANGE2;
|
||||
state.cur_event.value = ptr[7] << 8 ^ ptr[6];
|
||||
event_end(&state);
|
||||
break;
|
||||
case 24:
|
||||
state.cur_event.name = "gaschange"s;
|
||||
state.cur_event.type = SAMPLE_EVENT_GASCHANGE2;
|
||||
state.cur_event.value = ptr[7] << 8 ^ ptr[6];
|
||||
event_end(&state);
|
||||
// This is both a mode change and a gas change event
|
||||
// so we encode it as two separate events.
|
||||
event_start(&state);
|
||||
state.cur_event.name = "Change Mode"s;
|
||||
switch (ptr[8]) {
|
||||
case 1:
|
||||
state.cur_event.name += ": OC"s;
|
||||
break;
|
||||
case 2:
|
||||
state.cur_event.name += ": CCR"s;
|
||||
break;
|
||||
case 3:
|
||||
state.cur_event.name += ": mCCR"s;
|
||||
break;
|
||||
case 4:
|
||||
state.cur_event.name += ": Free"s;
|
||||
break;
|
||||
case 5:
|
||||
state.cur_event.name += ": Gauge"s;
|
||||
break;
|
||||
case 6:
|
||||
state.cur_event.name += ": ASCR"s;
|
||||
break;
|
||||
case 7:
|
||||
state.cur_event.name += ": PSCR"s;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
event_end(&state);
|
||||
break;
|
||||
case 25:
|
||||
// uint16_t solenoid_bitmap = (ptr[7] << 8) + (ptr[6] << 0);
|
||||
// uint32_t time = (ptr[11] << 24) + (ptr[10] << 16) + (ptr[9] << 8) + (ptr[8] << 0);
|
||||
state.cur_event.name = format_string_std("CCR O2 solenoid %s", ptr[12] ? "opened": "closed");
|
||||
break;
|
||||
case 26:
|
||||
state.cur_event.name = "User mark"s;
|
||||
break;
|
||||
case 27:
|
||||
state.cur_event.name = format_string_std("%sGF Switch (%d/%d)", ptr[6] ? "Bailout, ": "", ptr[7], ptr[8]);
|
||||
break;
|
||||
case 28:
|
||||
state.cur_event.name = "Peer Up"s;
|
||||
break;
|
||||
case 29:
|
||||
state.cur_event.name = "HS Up"s;
|
||||
break;
|
||||
case 30:
|
||||
state.cur_event.name = format_string_std("CNS %d%%", ptr[6]);
|
||||
break;
|
||||
default:
|
||||
// No values above 30 had any description
|
||||
break;
|
||||
}
|
||||
event_end(&state);
|
||||
break;
|
||||
case 6:
|
||||
/* device configuration */
|
||||
switch (((ptr[3] & 0x7f) << 3) + ((ptr[2] & 0xe0) >> 5)) {
|
||||
// Buffer to print extra string into
|
||||
// Local variables to temporary decode into
|
||||
struct tm tm;
|
||||
const char *device;
|
||||
const char *deep_stops;
|
||||
case 0: // TEST_CCR_FULL_1
|
||||
utc_mkdate(parse_dlf_timestamp(ptr + 12), &tm);
|
||||
add_extra_data(state.cur_dc, "TEST_CCR_FULL_1",
|
||||
format_string_std("START=%04u-%02u-%02u %02u:%02u:%02u,TEST=%02X%02X%02X%02X,RESULT=%02X%02X%02X%02X",
|
||||
tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, ptr[7], ptr[6], ptr[5], ptr[4], ptr[11], ptr[10], ptr[9], ptr[8]));
|
||||
break;
|
||||
case 1: // TEST_CCR_PARTIAL_1
|
||||
utc_mkdate(parse_dlf_timestamp(ptr + 12), &tm);
|
||||
add_extra_data(state.cur_dc, "TEST_CCR_PARTIAL_1",
|
||||
format_string_std("START=%04u-%02u-%02u %02u:%02u:%02u,TEST=%02X%02X%02X%02X,RESULT=%02X%02X%02X%02X",
|
||||
tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, ptr[7], ptr[6], ptr[5], ptr[4], ptr[11], ptr[10], ptr[9], ptr[8]));
|
||||
break;
|
||||
case 2: // CFG_OXYGEN_CALIBRATION
|
||||
utc_mkdate(parse_dlf_timestamp(ptr + 12), &tm);
|
||||
o2_sensor_calibration_values[0] = (ptr[5] << 8) + ptr[4];
|
||||
o2_sensor_calibration_values[1] = (ptr[7] << 8) + ptr[6];
|
||||
o2_sensor_calibration_values[2] = (ptr[9] << 8) + ptr[8];
|
||||
o2_sensor_calibration_values[3] = (ptr[11] << 8) + ptr[10];
|
||||
add_extra_data(state.cur_dc, "CFG_OXYGEN_CALIBRATION",
|
||||
format_string_std("%04u,%04u,%04u,%04u,TIME=%04u-%02u-%02u %02u:%02u:%02u",
|
||||
o2_sensor_calibration_values[0], o2_sensor_calibration_values[1], o2_sensor_calibration_values[2], o2_sensor_calibration_values[3], tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec));
|
||||
break;
|
||||
case 3: // CFG_SERIAL
|
||||
add_extra_data(state.cur_dc, "CFG_SERIAL",
|
||||
format_string_std("PRODUCT=%c%c%c%c,SERIAL=%c%c%c%c%c%c%c%c",
|
||||
ptr[4], ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15]));
|
||||
break;
|
||||
case 4: // CFG_CONFIG_DECO
|
||||
switch ((ptr[5] & 0xC0) >> 6) {
|
||||
case 0:
|
||||
deep_stops = "none";
|
||||
break;
|
||||
case 1:
|
||||
deep_stops = "Pyle";
|
||||
break;
|
||||
case 2:
|
||||
deep_stops = "Sladek";
|
||||
break;
|
||||
default:
|
||||
deep_stops = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
add_extra_data(state.cur_dc, "CFG_CONFIG_DECO part 1",
|
||||
format_string_std("%s,%s,%s,safety stop required=%s,last_stop=%s,deco_algorithm=%s,stop_rounding=%u,deep_stops=%s",
|
||||
(ptr[4] & 0x80) ? "imperial" : "metric", (ptr[4] & 0x40) ? "sea" : "fresh", (ptr[4] & 0x30) ? "stops" : "ceiling", (ptr[4] & 0x10) ? "yes" : "no", (ptr[4] & 0x08) ? "6m" : "3m", (ptr[4] & 0x04) ? "VPM" : "Buhlmann+GF", (ptr[4] & 0x03) ? (ptr[4] & 0x03) * 30 : 1, deep_stops));
|
||||
add_extra_data(state.cur_dc, "CFG_CONFIG_DECO part 2",
|
||||
format_string_std("deep_stop_len=%u min,gas_switch_len=%u min,gf_low=%u,gf_high=%u,gf_low_bailout=%u,gf_high_bailout=%u,ppO2_low=%4.2f,ppO2_high=%4.2f",
|
||||
(ptr[5] & 0x38) >> 3, ptr[5] & 0x07, ptr[6], ptr[7], ptr[8], ptr[9], ptr[10] / 100.0f, ptr[11] / 100.0f));
|
||||
add_extra_data(state.cur_dc, "CFG_CONFIG_DECO part 3",
|
||||
format_string_std("alarm_global=%u,alarm_cns=%u,alarm_ppO2=%u,alarm_ceiling=%u,alarm_stop_miss=%u,alarm_decentrate=%u,alarm_ascentrate=%u",
|
||||
(ptr[12] & 0x80) >> 7, (ptr[12] & 0x40) >> 6, (ptr[12] & 0x20) >> 5, (ptr[12] & 0x10) >> 4, (ptr[12] & 0x08) >> 3, (ptr[12] & 0x04) >> 2, (ptr[12] & 0x02) >> 1));
|
||||
break;
|
||||
case 5: // CFG_VERSION
|
||||
switch (ptr[4]) {
|
||||
case 0:
|
||||
device = "FREEDOM";
|
||||
break;
|
||||
case 1:
|
||||
device = "LIBERTY_CU";
|
||||
break;
|
||||
case 2:
|
||||
device = "LIBERTY_HS";
|
||||
break;
|
||||
default:
|
||||
device = "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
add_extra_data(state.cur_dc, "CFG_VERSION",
|
||||
format_string_std("DEVICE=%s,HW=%d.%d,FW=%d.%d.%d.%d,FLAGS=%04X",
|
||||
device, ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], (ptr[15] << 24) + (ptr[14] << 16) + (ptr[13] << 8) + (ptr[12]), (ptr[11] << 8) + ptr[10]));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
/* measure record */
|
||||
switch (ptr[2] >> 5) {
|
||||
case 1:
|
||||
/* Record starting battery level */
|
||||
if (!battery_start.volt1 && !battery_start.volt2) {
|
||||
battery_start.volt1 = (ptr[5] << 8) + ptr[4];
|
||||
battery_start.percent1 = ptr[6];
|
||||
battery_start.volt2 = (ptr[9] << 8) + ptr[8];
|
||||
battery_start.percent2 = ptr[10];
|
||||
}
|
||||
|
||||
/* Measure Battery, recording the last reading only */
|
||||
battery_end.volt1 = (ptr[5] << 8) + ptr[4];
|
||||
battery_end.percent1 = ptr[6];
|
||||
battery_end.volt2 = (ptr[9] << 8) + ptr[8];
|
||||
battery_end.percent2 = ptr[10];
|
||||
break;
|
||||
case 2:
|
||||
/* Measure He */
|
||||
//report_info("%ds he2 cells(0.01 mV): %d %d", time, (ptr[5] << 8) + ptr[4], (ptr[9] << 8) + ptr[8]);
|
||||
break;
|
||||
case 3:
|
||||
/* Measure Oxygen */
|
||||
//report_info("%d s: o2 cells(0.01 mV): %d %d %d %d", time, (ptr[5] << 8) + ptr[4], (ptr[7] << 8) + ptr[6], (ptr[9] << 8) + ptr[8], (ptr[11] << 8) + ptr[10]);
|
||||
// [Pa/mV] coeficient O2
|
||||
// 100 Pa == 1 mbar
|
||||
sample_start(&state);
|
||||
state.cur_sample->time.seconds = time;
|
||||
state.cur_sample->o2sensor[0].mbar = ( ((ptr[5] << 8) + ptr[4]) * o2_sensor_calibration_values[0]) / 10000;
|
||||
state.cur_sample->o2sensor[1].mbar = ( ((ptr[7] << 8) + ptr[6]) * o2_sensor_calibration_values[1]) / 10000;
|
||||
state.cur_sample->o2sensor[2].mbar = ( ((ptr[9] << 8) + ptr[8]) * o2_sensor_calibration_values[2]) / 10000;
|
||||
state.cur_sample->o2sensor[3].mbar = ( ((ptr[11] << 8) + ptr[10]) * o2_sensor_calibration_values[3]) / 10000;
|
||||
sample_end(&state);
|
||||
break;
|
||||
case 4:
|
||||
/* Measure GPS */
|
||||
state.cur_location.lat.udeg = (int)((ptr[7] << 24) + (ptr[6] << 16) + (ptr[5] << 8) + (ptr[4] << 0));
|
||||
state.cur_location.lon.udeg = (int)((ptr[11] << 24) + (ptr[10] << 16) + (ptr[9] << 8) + (ptr[8] << 0));
|
||||
state.log->sites.create("DLF imported"s, state.cur_location)->add_dive(state.cur_dive.get());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
/* Deco event */
|
||||
break;
|
||||
default:
|
||||
/* Unknown... */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Recording the starting battery status to extra data */
|
||||
if (battery_start.volt1) {
|
||||
std::string str = format_string_std("%dmV (%d%%)", battery_start.volt1, battery_start.percent1);
|
||||
add_extra_data(state.cur_dc, "Battery 1 (start)", str.c_str());
|
||||
|
||||
str = format_string_std("%dmV (%d%%)", battery_start.volt2, battery_start.percent2);
|
||||
add_extra_data(state.cur_dc, "Battery 2 (start)", str.c_str());
|
||||
}
|
||||
|
||||
/* Recording the ending battery status to extra data */
|
||||
if (battery_end.volt1) {
|
||||
std::string str = format_string_std("%dmV (%d%%)", battery_end.volt1, battery_end.percent1);
|
||||
add_extra_data(state.cur_dc, "Battery 1 (end)", str.c_str());
|
||||
|
||||
str = format_string_std("%dmV (%d%%)", battery_end.volt2, battery_end.percent2);
|
||||
add_extra_data(state.cur_dc, "Battery 2 (end)", str.c_str());
|
||||
}
|
||||
|
||||
divecomputer_end(&state);
|
||||
dive_end(&state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void parse_xml_init()
|
||||
{
|
||||
LIBXML_TEST_VERSION
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue