Next round of api improvements.

Jef Driesen jefdriesen at telenet.be
Wed Dec 5 16:00:15 UTC 2012


Hi,

There have been some interesting discussions since I posted my original 
email. Some of those discussions happened off list (mainly because they 
were already ongoing before I send out my email), so I think it's a good 
idea to summarize what has been discussed so far, the decisions that 
have been made already (or not), new issues that popped up etc.

BTW, there will be a slight change of plans regarding the next v0.3 
release. The changes that are being discussed in this thread, will be 
postponed until after the v0.3 release. The v0.3 release will be an 
intermediate release, with some smaller api cleanups (which should not 
affect most apps), some new features and bugfixes. This will also give 
us some more time to work out the new api design.


> 1. Object ownership, lifetime and memory management.
> =====================================================

The application will own all objects. Simplicity and consistency is 
considered more important than efficiency.

> 2. Querying available sample values?
> =====================================

The current proposal is that each sample will provide a bitmap with the 
available values. We introduce some new function to retrieve the bitmap 
(tentative name, suggestions are welcome):

dc_sample_get_available (sample, &bitmap);

and then applications can test the returned bitmap for the individual 
types, and if present, call the corresponding getter function:

if (bitmap & DC_SAMPLE_FOO) {
     dc_sample_get_foo (sample, &foo)
}

> 3. Supported dive and sample data
> ==================================

3a. Dive data
==============

The original list hasn't changed much:

  * date/time
  * divetime
  * maxdepth
  * gasmixes
  * tank pressures (begin/end)
  * temperature

For multivalued fields, like the gas mixes and tank pressure, the 
current proposal is to use a struct with a count and a pointer to the 
actual data array:

struct {
     unsigned int count;
     foo_t *foo;
};

Note that such a struct would behave a bit different from the others. 
Normally the caller passes a pointer to a struct (or plain C datatype) 
to the getter function, so the storage is provided by the caller and the 
getter function just fills in the value(s). But in this case we return a 
pointer to a foo_t struct that is not owned by the sample object. This 
may not be such a big deal considering the app will own the sample 
object, but I wanted to make sure this doesn't go unnoticed :-)


Support for salinity and atmospheric pressure has already been 
requested. The primary use-case is probably for doing decompression 
calculations. This has already been implemented in the master branch 
using a structure like this:

struct dc_salinity_t {
     enum {DC_WATER_FRESH, DC_WATER_SALT} type;
     density; /* Optional, zero if unavailable. */
};

For devices which don't support atmospheric pressure directly, and 
provide an altitude ranges instead (e.g. "0-300m" "300-1000m" 
"1000m-1500m), an estimation for the atmospheric pressure can be 
calculated with the barometric formula [1]. For ranges, the upper value 
of the range is probably the best choice, because it yields the lowest 
pressure. However, because diving at sealevel is probably the most 
common case, an exception could be made to consider the first range 
always at sealevel (e.g 1013.25 mbar).


There has been some discussion regarding the exact semantics of the 
temperature field. On one hand it's important to clearly define the 
exact semantics, but on the other hand the device may provide one or 
more temperature temperature values with some different semantics. For 
example we can define the temperature field to be the minimum 
temperature, but the device can provide the minimum, maximum or average 
value, or the temperature before and after the dive, or the temperature 
at maximum depth, or one or more of the above. How do we support this?

One option is to keep the exact semantics vague, and just supply 
whatever temperature value the device supplies. This is not ideal, 
because it leaves applications that care about the exact interpretation 
in the cold, and it also doesn't work well in case the device provides 
more than one value.

An alternative option is to move the temperature data into the samples. 
All the values mentioned above can easily be attached to the correct 
sample. You still won't get a full temperature profile (only a few data 
points), but at least their is no confusion about the semantics. For 
example a temperature value attached to sample at maximum depth, is 
clearly the temperature at max depth, and so on.

Another suggestion was to use flags to make the exact semantics clear. 
For example if the default semantics is the minimum temperature, provide 
a flag to overrule this interpretation with another one (e.g at max 
depth, etc).

struct temperature {
     flags;
     value;
     ... /* Maybe multiple values here? */
};

And last but not least we can provide a struct with all possible 
values:

struct temperature {
     minimum;
     maximum;
     average;
     ...
};

and then provide some means to let the application know which values 
are available (using a bitmap again, or some magic values to indicate 
"not present").

No decision for the temperature issue has been made yet.

3b. Sample data
================

The basic list doesn't need much discussion:

  * time
  * depth
  * temperature
  * tank pressure

There are also a couple less important ones, but as long as they are 
reasonable device independent, I see no reason not to support them too:

  * heartrate
  * airtime
  * CNS/OTU
  * ...

Note that this is definitely not a complete list. We'll probably need a 
few extra types for tec divers (setpoints), and there may be others that 
I forgot.


There has been some discussion regarding the CNS values (but the 
underlying discussion applies to any other type too). The natural unit 
for the CNS values is obviously a percentage. But there are devices that 
don't supply a percentage. For example the Suunto has OLF (Oxygen Limit 
Fraction), which is hybrid between CNS and OTU (e.g. whichever is 
highest), and Oceanic has their 02 bar graphs. Although both give some 
indication of the CNS loading, they are not easily translated to a 
percentage.

What to do in this case? Just not support it, or again provide some 
flag with the exact interpretation?

3c. Events
===========

The current proposal is to reserve the events exclusively for things 
that have no duration (and thus no need for the begin/end flags) and 
don't need to carry any data values. In that case, we can use a simple 
bitfield to get all the events for the sample at once.

dc_sample_get_available (sample, &bitmap);

if (bitmap & DC_SAMPLE_EVENTS) {
     dc_sample_get_events (sample, &events);

     if (events & DC_SAMPLE_EVENT_BOOKMARK) {
         /* Bookmark event. */
     }
     if (events & DC_SAMPLE_EVENT_VIOLATION) {
         /* Decostop violation event. */
     }
}

While this should work well for true events like the decostop 
violations, bookmarks, etc we'll need another solution for things like 
gas changes, decompression info, etc. The idea is deliver this info as 
sample values, rather than events.


For example the gasswitch event would be changed into an "active 
gasmix" sample value. The main difference is that you will now get the 
current gasmix on every sample, and not just the gaschange. For the 
gasmix sample value, the corresponding data type would be the index of 
the gasmix in the header (see above).


Decompression data can be supported in a similar way. For each sample 
you can get the deco status, with a data structure like this:

dc_deco_t {
     enum {NDL, DECOSTOP} type;
     time; /* Optional */
     depth; /* Optional */
};

If you're not in deco, the type will be set to NDL, and the time 
contains the remaining no decompression limit (if available). If you're 
in deco, the type will be set to DECOSTOP, and the time and depth 
contain the time and depth of the next decompression stop (if 
available). With such a structure we can support both devices that 
provide just a simple ndl/deco flag, or a some more detailed info.

We already committed some changes to the master branch to move into 
that direction. The DC_EVENT_DECOSTOP now contains the depth (in meters) 
and time (in seconds) as two packed 16bit values, and a new DC_EVENT_NDL 
was introduced. It's not perfect yet, because for the current api we 
were limited to the existing data structures (hence the packing), but 
it's a step in the direction of the model explained here.

Of course we can consider to extend the type with deepstops and safety 
stops, or add an extra field for TTS (Time To Surface), and things like 
that. But the main point is that we move away from the event model as 
much as possible.

3d. Units
==========

The two choices are SI (second, meter, Kelvin, Pascal) or metric 
(second, meter, Celsius, bar). The only difference between the pressure 
units "Pascal" and "bar" is a scaling factor, so then it comes down to 
Kelvin or Celsius for the temperatures.

I'm also seriously considering to adopt the subsurface style unit 
system, where the units are carefully chosen to make them fit into an 
integer: second, millimeter, milli Kelvin and millibar. This should 
provide plenty of precision for our purpose, while avoiding all kinds of 
floating point issues, such as rounding (e.g. 15.0 may actually be 
14.99999) and equality (comparing floating point's for equality is 
tricky).

No decision has been made yet. I would like to know what application 
developers (and not just the subsurface ones) think of this.

3e. Vendor extensions
======================

We want some way to support vendor specific extensions. But it's not 
completely clear yet how the interface should look like. It's not the 
highest priority, because the above is far more important, but it's good 
to keep extensibility in mind!

Anyway, this has been discussed on the mailinglist, so I won't repeat 
all the proposals again here.



[1] http://en.wikipedia.org/wiki/Barometric_formula

Jef




More information about the Devel mailing list