Add support for imperial units in the xml output.
Libdivecomputer always uses metric units internally. But when reverse engineering a device that stores everything using imperial units, it's very convenient to be able to switch the output to imperial units too.
This commit is contained in:
parent
8ab3fb0542
commit
469717a2a1
@ -246,6 +246,7 @@ dctool_download_run (int argc, char *argv[], dc_context_t *context, dc_descripto
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_buffer_t *fingerprint = NULL;
|
||||
dctool_output_t *output = NULL;
|
||||
dctool_units_t units = DCTOOL_UNITS_METRIC;
|
||||
|
||||
// Default option values.
|
||||
unsigned int help = 0;
|
||||
@ -256,7 +257,7 @@ dctool_download_run (int argc, char *argv[], dc_context_t *context, dc_descripto
|
||||
|
||||
// Parse the command-line options.
|
||||
int opt = 0;
|
||||
const char *optstring = "ho:p:c:f:";
|
||||
const char *optstring = "ho:p:c:f:u:";
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
struct option options[] = {
|
||||
{"help", no_argument, 0, 'h'},
|
||||
@ -264,6 +265,7 @@ dctool_download_run (int argc, char *argv[], dc_context_t *context, dc_descripto
|
||||
{"fingerprint", required_argument, 0, 'p'},
|
||||
{"cache", required_argument, 0, 'c'},
|
||||
{"format", required_argument, 0, 'f'},
|
||||
{"units", required_argument, 0, 'u'},
|
||||
{0, 0, 0, 0 }
|
||||
};
|
||||
while ((opt = getopt_long (argc, argv, optstring, options, NULL)) != -1) {
|
||||
@ -286,6 +288,12 @@ dctool_download_run (int argc, char *argv[], dc_context_t *context, dc_descripto
|
||||
case 'f':
|
||||
format = optarg;
|
||||
break;
|
||||
case 'u':
|
||||
if (strcmp (optarg, "metric") == 0)
|
||||
units = DCTOOL_UNITS_METRIC;
|
||||
if (strcmp (optarg, "imperial") == 0)
|
||||
units = DCTOOL_UNITS_IMPERIAL;
|
||||
break;
|
||||
default:
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@ -307,7 +315,7 @@ dctool_download_run (int argc, char *argv[], dc_context_t *context, dc_descripto
|
||||
if (strcasecmp(format, "raw") == 0) {
|
||||
output = dctool_raw_output_new (filename);
|
||||
} else if (strcasecmp(format, "xml") == 0) {
|
||||
output = dctool_xml_output_new (filename);
|
||||
output = dctool_xml_output_new (filename, units);
|
||||
} else {
|
||||
message ("Unknown output format: %s\n", format);
|
||||
exitcode = EXIT_FAILURE;
|
||||
@ -348,12 +356,14 @@ const dctool_command_t dctool_download = {
|
||||
" -p, --fingerprint <data> Fingerprint data (hexadecimal)\n"
|
||||
" -c, --cache <directory> Cache directory\n"
|
||||
" -f, --format <format> Output format\n"
|
||||
" -u, --units <units> Set units (metric or imperial)\n"
|
||||
#else
|
||||
" -h Show help message\n"
|
||||
" -o <filename> Output filename\n"
|
||||
" -p <fingerprint> Fingerprint data (hexadecimal)\n"
|
||||
" -c <directory> Cache directory\n"
|
||||
" -f <format> Output format\n"
|
||||
" -u <units> Set units (metric or imperial)\n"
|
||||
#endif
|
||||
"\n"
|
||||
"Supported output formats:\n"
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
@ -196,6 +197,7 @@ dctool_parse_run (int argc, char *argv[], dc_context_t *context, dc_descriptor_t
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_buffer_t *buffer = NULL;
|
||||
dctool_output_t *output = NULL;
|
||||
dctool_units_t units = DCTOOL_UNITS_METRIC;
|
||||
|
||||
// Default option values.
|
||||
unsigned int help = 0;
|
||||
@ -205,13 +207,14 @@ dctool_parse_run (int argc, char *argv[], dc_context_t *context, dc_descriptor_t
|
||||
|
||||
// Parse the command-line options.
|
||||
int opt = 0;
|
||||
const char *optstring = "ho:d:s:";
|
||||
const char *optstring = "ho:d:s:u:";
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
struct option options[] = {
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"output", required_argument, 0, 'o'},
|
||||
{"devtime", required_argument, 0, 'd'},
|
||||
{"systime", required_argument, 0, 's'},
|
||||
{"units", required_argument, 0, 'u'},
|
||||
{0, 0, 0, 0 }
|
||||
};
|
||||
while ((opt = getopt_long (argc, argv, optstring, options, NULL)) != -1) {
|
||||
@ -231,6 +234,12 @@ dctool_parse_run (int argc, char *argv[], dc_context_t *context, dc_descriptor_t
|
||||
case 's':
|
||||
systime = strtoll (optarg, NULL, 0);
|
||||
break;
|
||||
case 'u':
|
||||
if (strcmp (optarg, "metric") == 0)
|
||||
units = DCTOOL_UNITS_METRIC;
|
||||
if (strcmp (optarg, "imperial") == 0)
|
||||
units = DCTOOL_UNITS_IMPERIAL;
|
||||
break;
|
||||
default:
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@ -246,7 +255,7 @@ dctool_parse_run (int argc, char *argv[], dc_context_t *context, dc_descriptor_t
|
||||
}
|
||||
|
||||
// Create the output.
|
||||
output = dctool_xml_output_new (filename);
|
||||
output = dctool_xml_output_new (filename, units);
|
||||
if (output == NULL) {
|
||||
message ("Failed to create the output.\n");
|
||||
exitcode = EXIT_FAILURE;
|
||||
@ -295,10 +304,12 @@ const dctool_command_t dctool_parse = {
|
||||
" -o, --output <filename> Output filename\n"
|
||||
" -d, --devtime <timestamp> Device time\n"
|
||||
" -s, --systime <timestamp> System time\n"
|
||||
" -u, --units <units> Set units (metric or imperial)\n"
|
||||
#else
|
||||
" -h Show help message\n"
|
||||
" -o <filename> Output filename\n"
|
||||
" -d <devtime> Device time\n"
|
||||
" -s <systime> System time\n"
|
||||
" -u <units> Set units (metric or imperial)\n"
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -31,8 +31,13 @@ extern "C" {
|
||||
|
||||
typedef struct dctool_output_t dctool_output_t;
|
||||
|
||||
typedef enum dctool_units_t {
|
||||
DCTOOL_UNITS_METRIC,
|
||||
DCTOOL_UNITS_IMPERIAL
|
||||
} dctool_units_t;
|
||||
|
||||
dctool_output_t *
|
||||
dctool_xml_output_new (const char *filename);
|
||||
dctool_xml_output_new (const char *filename, dctool_units_t units);
|
||||
|
||||
dctool_output_t *
|
||||
dctool_raw_output_new (const char *template);
|
||||
|
||||
@ -23,6 +23,8 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <libdivecomputer/units.h>
|
||||
|
||||
#include "output-private.h"
|
||||
#include "utils.h"
|
||||
|
||||
@ -32,6 +34,7 @@ static dc_status_t dctool_xml_output_free (dctool_output_t *output);
|
||||
typedef struct dctool_xml_output_t {
|
||||
dctool_output_t base;
|
||||
FILE *ostream;
|
||||
dctool_units_t units;
|
||||
} dctool_xml_output_t;
|
||||
|
||||
static const dctool_output_vtable_t xml_vtable = {
|
||||
@ -42,9 +45,50 @@ static const dctool_output_vtable_t xml_vtable = {
|
||||
|
||||
typedef struct sample_data_t {
|
||||
FILE *ostream;
|
||||
dctool_units_t units;
|
||||
unsigned int nsamples;
|
||||
} sample_data_t;
|
||||
|
||||
static double
|
||||
convert_depth (double value, dctool_units_t units)
|
||||
{
|
||||
if (units == DCTOOL_UNITS_IMPERIAL) {
|
||||
return value / FEET;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
static double
|
||||
convert_temperature (double value, dctool_units_t units)
|
||||
{
|
||||
if (units == DCTOOL_UNITS_IMPERIAL) {
|
||||
return value * (9.0 / 5.0) + 32.0;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
static double
|
||||
convert_pressure (double value, dctool_units_t units)
|
||||
{
|
||||
if (units == DCTOOL_UNITS_IMPERIAL) {
|
||||
return value * BAR / PSI;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
static double
|
||||
convert_volume (double value, dctool_units_t units)
|
||||
{
|
||||
if (units == DCTOOL_UNITS_IMPERIAL) {
|
||||
return value / 1000.0 / CUFT;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sample_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata)
|
||||
{
|
||||
@ -68,13 +112,17 @@ sample_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata)
|
||||
fprintf (sampledata->ostream, " <time>%02u:%02u</time>\n", value.time / 60, value.time % 60);
|
||||
break;
|
||||
case DC_SAMPLE_DEPTH:
|
||||
fprintf (sampledata->ostream, " <depth>%.2f</depth>\n", value.depth);
|
||||
fprintf (sampledata->ostream, " <depth>%.2f</depth>\n",
|
||||
convert_depth(value.depth, sampledata->units));
|
||||
break;
|
||||
case DC_SAMPLE_PRESSURE:
|
||||
fprintf (sampledata->ostream, " <pressure tank=\"%u\">%.2f</pressure>\n", value.pressure.tank, value.pressure.value);
|
||||
fprintf (sampledata->ostream, " <pressure tank=\"%u\">%.2f</pressure>\n",
|
||||
value.pressure.tank,
|
||||
convert_pressure(value.pressure.value, sampledata->units));
|
||||
break;
|
||||
case DC_SAMPLE_TEMPERATURE:
|
||||
fprintf (sampledata->ostream, " <temperature>%.2f</temperature>\n", value.temperature);
|
||||
fprintf (sampledata->ostream, " <temperature>%.2f</temperature>\n",
|
||||
convert_temperature(value.temperature, sampledata->units));
|
||||
break;
|
||||
case DC_SAMPLE_EVENT:
|
||||
if (value.event.type != SAMPLE_EVENT_GASCHANGE && value.event.type != SAMPLE_EVENT_GASCHANGE2) {
|
||||
@ -108,7 +156,9 @@ sample_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata)
|
||||
break;
|
||||
case DC_SAMPLE_DECO:
|
||||
fprintf (sampledata->ostream, " <deco time=\"%u\" depth=\"%.2f\">%s</deco>\n",
|
||||
value.deco.time, value.deco.depth, decostop[value.deco.type]);
|
||||
value.deco.time,
|
||||
convert_depth(value.deco.depth, sampledata->units),
|
||||
decostop[value.deco.type]);
|
||||
break;
|
||||
case DC_SAMPLE_GASMIX:
|
||||
fprintf (sampledata->ostream, " <gasmix>%u</gasmix>\n", value.gasmix);
|
||||
@ -119,7 +169,7 @@ sample_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata)
|
||||
}
|
||||
|
||||
dctool_output_t *
|
||||
dctool_xml_output_new (const char *filename)
|
||||
dctool_xml_output_new (const char *filename, dctool_units_t units)
|
||||
{
|
||||
dctool_xml_output_t *output = NULL;
|
||||
|
||||
@ -138,6 +188,8 @@ dctool_xml_output_new (const char *filename)
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
output->units = units;
|
||||
|
||||
fprintf (output->ostream, "<device>\n");
|
||||
|
||||
return (dctool_output_t *) output;
|
||||
@ -158,6 +210,7 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u
|
||||
sample_data_t sampledata = {0};
|
||||
sampledata.nsamples = 0;
|
||||
sampledata.ostream = output->ostream;
|
||||
sampledata.units = output->units;
|
||||
|
||||
fprintf (output->ostream, "<dive>\n<number>%u</number>\n<size>%u</size>\n", abstract->number, size);
|
||||
|
||||
@ -203,7 +256,7 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u
|
||||
}
|
||||
|
||||
fprintf (output->ostream, "<maxdepth>%.2f</maxdepth>\n",
|
||||
maxdepth);
|
||||
convert_depth(maxdepth, output->units));
|
||||
|
||||
// Parse the temperature.
|
||||
message ("Parsing the temperature.\n");
|
||||
@ -222,7 +275,8 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u
|
||||
|
||||
if (status != DC_STATUS_UNSUPPORTED) {
|
||||
fprintf (output->ostream, "<temperature type=\"%s\">%.1f</temperature>\n",
|
||||
names[i], temperature);
|
||||
names[i],
|
||||
convert_temperature(temperature, output->units));
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,13 +338,16 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u
|
||||
" <type>%s</type>\n"
|
||||
" <volume>%.1f</volume>\n"
|
||||
" <workpressure>%.2f</workpressure>\n",
|
||||
names[tank.type], tank.volume, tank.workpressure);
|
||||
names[tank.type],
|
||||
convert_volume(tank.volume, output->units),
|
||||
convert_pressure(tank.workpressure, output->units));
|
||||
}
|
||||
fprintf (output->ostream,
|
||||
" <beginpressure>%.2f</beginpressure>\n"
|
||||
" <endpressure>%.2f</endpressure>\n"
|
||||
"</tank>\n",
|
||||
tank.beginpressure, tank.endpressure);
|
||||
convert_pressure(tank.beginpressure, output->units),
|
||||
convert_pressure(tank.endpressure, output->units));
|
||||
}
|
||||
|
||||
// Parse the dive mode.
|
||||
@ -333,7 +390,7 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u
|
||||
|
||||
if (status != DC_STATUS_UNSUPPORTED) {
|
||||
fprintf (output->ostream, "<atmospheric>%.5f</atmospheric>\n",
|
||||
atmospheric);
|
||||
convert_pressure(atmospheric, output->units));
|
||||
}
|
||||
|
||||
// Parse the sample data.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user