From 362fe3f936d2338160ced9de619950c7f6495ef8 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 17 Apr 2018 10:16:39 -0700 Subject: [PATCH] Add subsurface-specific DC field extension: descriptor/value strings The default libdivecomputer fields are good for structured data that has a well-defined format, like the cylinder information, or the temperature data. But it is entirely useless for miscellaneous divecomputer-specific information, where there is no standard way of representing the data across different kinds of dive computers. Examples of this include simple things like deco calculation algorithm (what kind of Buehlmann, gradient factor information or is it some vendor-specific mode?) and even something as trivial as a serial number. No, serial numbers aren't numbers. They are strings. Really. But this also includes much more complex data that is really specific to a particular dive computer or family: what the battery status is for the dive computer or the wireless transmitters it is connected to (sometimes it's a voltage, sometimes it's a percentage, sometimes it's just "good" or "marginal"). It also includes random incidental information like firmware version numbers (again, these are strings, not numbers, despite the name) or dive mode and personal adjustment information. So allow the dive computer to just give "extra information" in the form of an array of { key, value } string pairs. For my Perdix AI the information could be { "Serial", "370d1f24" } { "FW Version", "44" } { "Deco model", "GF 40/85" } { "Battery type", "3.6V Saft" } { "Battery at end", "3.4 V" } and for my EON Steel with three wireless transmitters connected it can look like this: { "Serial", "1742104730" } { "FW Version", "1.6.5" } { "HW Version", "70.3.0" } { "Battery at start", "Charge: 83%, Voltage: 4.012V" } { "Deco algorithm", "Suunto Fused RGBM" } { "Personal Adjustment", "P-2" } { "Battery at end", "Charge: 79%, Voltage: 3.977V" } { "Dive Mode", "Trimix" } { "Desaturation Time", "7:53" } { "Transmitter ID", "1519107801" } { "Transmitter Battery at start", "87 %" } { "Transmitter Battery at end", "87 %" } { "Transmitter ID", "1550110028" } { "Transmitter Battery at start", "100 %" } { "Transmitter Battery at end", "100 %" } { "Transmitter ID", "1719102387" } { "Transmitter Battery at start", "100 %" } { "Transmitter Battery at end", "100 %" } so this data is inherently unstructured and dependent on the dive computer, but quite relevant to the diver. Subsurface shows this in the "Extra Info" panel for each dive computer. Also teach the example output-xml code about the new string field extension. That example output-xml code was written by Anton Lundin in the old Subsurface branch, and signed-off-by Dirk. The sign-offs here are taken from that original work. Signed-off-by: Anton Lundin Signed-off-by: Dirk Hohndel Signed-off-by: Linus Torvalds --- examples/output_xml.c | 18 ++++++++++++++++++ include/libdivecomputer/parser.h | 11 ++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/examples/output_xml.c b/examples/output_xml.c index b66fc27..1e9c569 100644 --- a/examples/output_xml.c +++ b/examples/output_xml.c @@ -400,6 +400,24 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u convert_pressure(atmospheric, output->units)); } + message ("Parsing strings.\n"); + int idx; + for (idx = 0; idx < 100; idx++) { + dc_field_string_t str = { NULL }; + status = dc_parser_get_field(parser, DC_FIELD_STRING, idx, &str); + if (status != DC_STATUS_SUCCESS && status != DC_STATUS_UNSUPPORTED) { + ERROR ("Error parsing strings"); + goto cleanup; + } + if (status == DC_STATUS_UNSUPPORTED) + break; + if (!str.desc || !str.value) + break; + fprintf (output->ostream, "\n", + str.desc, str.value); + + } + // Parse the sample data. message ("Parsing the sample data.\n"); status = dc_parser_samples_foreach (parser, sample_cb, &sampledata); diff --git a/include/libdivecomputer/parser.h b/include/libdivecomputer/parser.h index 98827f1..965deda 100644 --- a/include/libdivecomputer/parser.h +++ b/include/libdivecomputer/parser.h @@ -62,9 +62,13 @@ typedef enum dc_field_type_t { DC_FIELD_TEMPERATURE_MAXIMUM, DC_FIELD_TANK_COUNT, DC_FIELD_TANK, - DC_FIELD_DIVEMODE + DC_FIELD_DIVEMODE, + DC_FIELD_STRING, } dc_field_type_t; +// Make it easy to test support compile-time with "#ifdef DC_FIELD_STRING" +#define DC_FIELD_STRING DC_FIELD_STRING + typedef enum parser_sample_event_t { SAMPLE_EVENT_NONE, SAMPLE_EVENT_DECOSTOP, @@ -199,6 +203,11 @@ typedef struct dc_tank_t { double endpressure; /* End pressure (bar) */ } dc_tank_t; +typedef struct dc_field_string_t { + const char *desc; + const char *value; +} dc_field_string_t; + typedef union dc_sample_value_t { unsigned int time; double depth;