Implement the new field api for the Suunto devices.
This commit is contained in:
parent
7c00b1d74e
commit
014f7aa420
@ -38,6 +38,7 @@ struct suunto_d9_parser_t {
|
||||
|
||||
static parser_status_t suunto_d9_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static parser_status_t suunto_d9_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime);
|
||||
static parser_status_t suunto_d9_parser_get_field (parser_t *abstract, parser_field_type_t type, unsigned int flags, void *value);
|
||||
static parser_status_t suunto_d9_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata);
|
||||
static parser_status_t suunto_d9_parser_destroy (parser_t *abstract);
|
||||
|
||||
@ -45,7 +46,7 @@ static const parser_backend_t suunto_d9_parser_backend = {
|
||||
PARSER_TYPE_SUUNTO_D9,
|
||||
suunto_d9_parser_set_data, /* set_data */
|
||||
suunto_d9_parser_get_datetime, /* datetime */
|
||||
NULL, /* fields */
|
||||
suunto_d9_parser_get_field, /* fields */
|
||||
suunto_d9_parser_samples_foreach, /* samples_foreach */
|
||||
suunto_d9_parser_destroy /* destroy */
|
||||
};
|
||||
@ -136,6 +137,64 @@ suunto_d9_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime)
|
||||
}
|
||||
|
||||
|
||||
static parser_status_t
|
||||
suunto_d9_parser_get_field (parser_t *abstract, parser_field_type_t type, unsigned int flags, void *value)
|
||||
{
|
||||
suunto_d9_parser_t *parser = (suunto_d9_parser_t*) abstract;
|
||||
|
||||
const unsigned char *data = abstract->data;
|
||||
unsigned int size = abstract->size;
|
||||
|
||||
// Offset to the configuration data.
|
||||
unsigned int config = 0x3E - SKIP;
|
||||
if (parser->model == 0x12)
|
||||
config += 1; // D4
|
||||
if (parser->model == 0x15)
|
||||
config += 74; // HelO2
|
||||
if (size < config)
|
||||
return PARSER_STATUS_ERROR;
|
||||
|
||||
gasmix_t *gasmix = (gasmix_t *) value;
|
||||
|
||||
if (value) {
|
||||
switch (type) {
|
||||
case FIELD_TYPE_DIVETIME:
|
||||
if (parser->model == 0x12)
|
||||
*((unsigned int *) value) = array_uint16_le (data + 0x0F - SKIP);
|
||||
else if (parser->model == 0x15)
|
||||
*((unsigned int *) value) = array_uint16_le (data + 0x0F - SKIP + 2) * 60;
|
||||
else
|
||||
*((unsigned int *) value) = array_uint16_le (data + 0x0F - SKIP) * 60;
|
||||
break;
|
||||
case FIELD_TYPE_MAXDEPTH:
|
||||
*((double *) value) = array_uint16_le (data + 0x0D - SKIP) / 100.0;
|
||||
break;
|
||||
case FIELD_TYPE_GASMIX_COUNT:
|
||||
if (parser->model == 0x15) {
|
||||
*((unsigned int *) value) = 8;
|
||||
} else {
|
||||
*((unsigned int *) value) = 3;
|
||||
}
|
||||
break;
|
||||
case FIELD_TYPE_GASMIX:
|
||||
if (parser->model == 0x15) {
|
||||
gasmix->helium = data[0x58 - SKIP + 6 * flags + 2] / 100.0;
|
||||
gasmix->oxygen = data[0x58 - SKIP + 6 * flags + 1] / 100.0;
|
||||
} else {
|
||||
gasmix->helium = 0.0;
|
||||
gasmix->oxygen = data[0x25 - SKIP + flags] / 100.0;
|
||||
}
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
break;
|
||||
default:
|
||||
return PARSER_STATUS_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
return PARSER_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static parser_status_t
|
||||
suunto_d9_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata)
|
||||
{
|
||||
|
||||
@ -32,10 +32,15 @@ typedef struct suunto_eon_parser_t suunto_eon_parser_t;
|
||||
struct suunto_eon_parser_t {
|
||||
parser_t base;
|
||||
int spyder;
|
||||
// Cached fields.
|
||||
unsigned int cached;
|
||||
unsigned int divetime;
|
||||
unsigned int maxdepth;
|
||||
};
|
||||
|
||||
static parser_status_t suunto_eon_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static parser_status_t suunto_eon_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime);
|
||||
static parser_status_t suunto_eon_parser_get_field (parser_t *abstract, parser_field_type_t type, unsigned int flags, void *value);
|
||||
static parser_status_t suunto_eon_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata);
|
||||
static parser_status_t suunto_eon_parser_destroy (parser_t *abstract);
|
||||
|
||||
@ -43,7 +48,7 @@ static const parser_backend_t suunto_eon_parser_backend = {
|
||||
PARSER_TYPE_SUUNTO_EON,
|
||||
suunto_eon_parser_set_data, /* set_data */
|
||||
suunto_eon_parser_get_datetime, /* datetime */
|
||||
NULL, /* fields */
|
||||
suunto_eon_parser_get_field, /* fields */
|
||||
suunto_eon_parser_samples_foreach, /* samples_foreach */
|
||||
suunto_eon_parser_destroy /* destroy */
|
||||
};
|
||||
@ -77,6 +82,9 @@ suunto_eon_parser_create (parser_t **out, int spyder)
|
||||
|
||||
// Set the default values.
|
||||
parser->spyder = spyder;
|
||||
parser->cached = 0;
|
||||
parser->divetime = 0;
|
||||
parser->maxdepth = 0;
|
||||
|
||||
*out = (parser_t*) parser;
|
||||
|
||||
@ -100,9 +108,16 @@ suunto_eon_parser_destroy (parser_t *abstract)
|
||||
static parser_status_t
|
||||
suunto_eon_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
suunto_eon_parser_t *parser = (suunto_eon_parser_t *) abstract;
|
||||
|
||||
if (! parser_is_suunto_eon (abstract))
|
||||
return PARSER_STATUS_TYPE_MISMATCH;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->divetime = 0;
|
||||
parser->maxdepth = 0;
|
||||
|
||||
return PARSER_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -138,6 +153,72 @@ suunto_eon_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime)
|
||||
}
|
||||
|
||||
|
||||
static parser_status_t
|
||||
suunto_eon_parser_get_field (parser_t *abstract, parser_field_type_t type, unsigned int flags, void *value)
|
||||
{
|
||||
suunto_eon_parser_t *parser = (suunto_eon_parser_t *) abstract;
|
||||
|
||||
const unsigned char *data = abstract->data;
|
||||
unsigned int size = abstract->size;
|
||||
|
||||
if (size < 13)
|
||||
return PARSER_STATUS_ERROR;
|
||||
|
||||
if (!parser->cached) {
|
||||
unsigned int interval = data[3];
|
||||
unsigned int nsamples = 0;
|
||||
unsigned int depth = 0, maxdepth = 0;
|
||||
unsigned int offset = 11;
|
||||
while (offset < size && data[offset] != 0x80) {
|
||||
unsigned char value = data[offset++];
|
||||
if (value < 0x7d || value > 0x82) {
|
||||
depth += (signed char) value;
|
||||
if (depth > maxdepth)
|
||||
maxdepth = depth;
|
||||
nsamples++;
|
||||
}
|
||||
}
|
||||
|
||||
// Store the offset to the end marker.
|
||||
unsigned int marker = offset;
|
||||
if (marker + 2 >= size || data[marker] != 0x80)
|
||||
return PARSER_STATUS_ERROR;
|
||||
|
||||
parser->cached = 1;
|
||||
parser->divetime = nsamples * interval;
|
||||
parser->maxdepth = maxdepth;
|
||||
}
|
||||
|
||||
gasmix_t *gasmix = (gasmix_t *) value;
|
||||
|
||||
if (value) {
|
||||
switch (type) {
|
||||
case FIELD_TYPE_DIVETIME:
|
||||
*((unsigned int *) value) = parser->divetime;
|
||||
break;
|
||||
case FIELD_TYPE_MAXDEPTH:
|
||||
*((double *) value) = parser->maxdepth * FEET;
|
||||
break;
|
||||
case FIELD_TYPE_GASMIX_COUNT:
|
||||
*((unsigned int *) value) = 1;
|
||||
break;
|
||||
case FIELD_TYPE_GASMIX:
|
||||
gasmix->helium = 0.0;
|
||||
if ((data[4] & 0x80) && !parser->spyder)
|
||||
gasmix->oxygen = data[0x05] / 100.0;
|
||||
else
|
||||
gasmix->oxygen = 0.21;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
break;
|
||||
default:
|
||||
return PARSER_STATUS_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
return PARSER_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static parser_status_t
|
||||
suunto_eon_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata)
|
||||
{
|
||||
|
||||
@ -30,9 +30,14 @@ typedef struct suunto_solution_parser_t suunto_solution_parser_t;
|
||||
|
||||
struct suunto_solution_parser_t {
|
||||
parser_t base;
|
||||
// Cached fields.
|
||||
unsigned int cached;
|
||||
unsigned int divetime;
|
||||
unsigned int maxdepth;
|
||||
};
|
||||
|
||||
static parser_status_t suunto_solution_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static parser_status_t suunto_solution_parser_get_field (parser_t *abstract, parser_field_type_t type, unsigned int flags, void *value);
|
||||
static parser_status_t suunto_solution_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata);
|
||||
static parser_status_t suunto_solution_parser_destroy (parser_t *abstract);
|
||||
|
||||
@ -40,7 +45,7 @@ static const parser_backend_t suunto_solution_parser_backend = {
|
||||
PARSER_TYPE_SUUNTO_SOLUTION,
|
||||
suunto_solution_parser_set_data, /* set_data */
|
||||
NULL, /* datetime */
|
||||
NULL, /* fields */
|
||||
suunto_solution_parser_get_field, /* fields */
|
||||
suunto_solution_parser_samples_foreach, /* samples_foreach */
|
||||
suunto_solution_parser_destroy /* destroy */
|
||||
};
|
||||
@ -72,6 +77,11 @@ suunto_solution_parser_create (parser_t **out)
|
||||
// Initialize the base class.
|
||||
parser_init (&parser->base, &suunto_solution_parser_backend);
|
||||
|
||||
// Set the default values.
|
||||
parser->cached = 0;
|
||||
parser->divetime = 0;
|
||||
parser->maxdepth = 0;
|
||||
|
||||
*out = (parser_t*) parser;
|
||||
|
||||
return PARSER_STATUS_SUCCESS;
|
||||
@ -94,13 +104,86 @@ suunto_solution_parser_destroy (parser_t *abstract)
|
||||
static parser_status_t
|
||||
suunto_solution_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
suunto_solution_parser_t *parser = (suunto_solution_parser_t *) abstract;
|
||||
|
||||
if (! parser_is_suunto_solution (abstract))
|
||||
return PARSER_STATUS_TYPE_MISMATCH;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->divetime = 0;
|
||||
parser->maxdepth = 0;
|
||||
|
||||
return PARSER_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static parser_status_t
|
||||
suunto_solution_parser_get_field (parser_t *abstract, parser_field_type_t type, unsigned int flags, void *value)
|
||||
{
|
||||
suunto_solution_parser_t *parser = (suunto_solution_parser_t *) abstract;
|
||||
|
||||
const unsigned char *data = abstract->data;
|
||||
unsigned int size = abstract->size;
|
||||
|
||||
if (size < 4)
|
||||
return PARSER_STATUS_ERROR;
|
||||
|
||||
if (!parser->cached) {
|
||||
unsigned int nsamples = 0;
|
||||
unsigned int depth = 0, maxdepth = 0;
|
||||
unsigned int offset = 3;
|
||||
while (offset < size && data[offset] != 0x80) {
|
||||
unsigned char value = data[offset++];
|
||||
if (value < 0x7e || value > 0x82) {
|
||||
depth += (signed char) value;
|
||||
if (value == 0x7D || value == 0x83) {
|
||||
if (offset + 1 > size)
|
||||
return PARSER_STATUS_ERROR;
|
||||
depth += (signed char) data[offset++];
|
||||
}
|
||||
if (depth > maxdepth)
|
||||
maxdepth = depth;
|
||||
nsamples++;
|
||||
}
|
||||
}
|
||||
|
||||
// Store the offset to the end marker.
|
||||
unsigned int marker = offset;
|
||||
if (marker + 1 >= size || data[marker] != 0x80)
|
||||
return PARSER_STATUS_ERROR;
|
||||
|
||||
parser->cached = 1;
|
||||
parser->divetime = (nsamples * 3 + data[marker + 1]) * 60;
|
||||
parser->maxdepth = maxdepth;
|
||||
}
|
||||
|
||||
gasmix_t *gasmix = (gasmix_t *) value;
|
||||
|
||||
if (value) {
|
||||
switch (type) {
|
||||
case FIELD_TYPE_DIVETIME:
|
||||
*((unsigned int *) value) = parser->divetime;
|
||||
break;
|
||||
case FIELD_TYPE_MAXDEPTH:
|
||||
*((double *) value) = parser->maxdepth * FEET;
|
||||
break;
|
||||
case FIELD_TYPE_GASMIX_COUNT:
|
||||
*((unsigned int *) value) = 1;
|
||||
break;
|
||||
case FIELD_TYPE_GASMIX:
|
||||
gasmix->helium = 0.0;
|
||||
gasmix->oxygen = 0.21;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
break;
|
||||
default:
|
||||
return PARSER_STATUS_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
return PARSER_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static parser_status_t
|
||||
suunto_solution_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata)
|
||||
{
|
||||
|
||||
@ -30,10 +30,15 @@ typedef struct suunto_vyper_parser_t suunto_vyper_parser_t;
|
||||
|
||||
struct suunto_vyper_parser_t {
|
||||
parser_t base;
|
||||
// Cached fields.
|
||||
unsigned int cached;
|
||||
unsigned int divetime;
|
||||
unsigned int maxdepth;
|
||||
};
|
||||
|
||||
static parser_status_t suunto_vyper_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static parser_status_t suunto_vyper_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime);
|
||||
static parser_status_t suunto_vyper_parser_get_field (parser_t *abstract, parser_field_type_t type, unsigned int flags, void *value);
|
||||
static parser_status_t suunto_vyper_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata);
|
||||
static parser_status_t suunto_vyper_parser_destroy (parser_t *abstract);
|
||||
|
||||
@ -41,7 +46,7 @@ static const parser_backend_t suunto_vyper_parser_backend = {
|
||||
PARSER_TYPE_SUUNTO_VYPER,
|
||||
suunto_vyper_parser_set_data, /* set_data */
|
||||
suunto_vyper_parser_get_datetime, /* datetime */
|
||||
NULL, /* fields */
|
||||
suunto_vyper_parser_get_field, /* fields */
|
||||
suunto_vyper_parser_samples_foreach, /* samples_foreach */
|
||||
suunto_vyper_parser_destroy /* destroy */
|
||||
};
|
||||
@ -73,6 +78,11 @@ suunto_vyper_parser_create (parser_t **out)
|
||||
// Initialize the base class.
|
||||
parser_init (&parser->base, &suunto_vyper_parser_backend);
|
||||
|
||||
// Set the default values.
|
||||
parser->cached = 0;
|
||||
parser->divetime = 0;
|
||||
parser->maxdepth = 0;
|
||||
|
||||
*out = (parser_t*) parser;
|
||||
|
||||
return PARSER_STATUS_SUCCESS;
|
||||
@ -95,9 +105,16 @@ suunto_vyper_parser_destroy (parser_t *abstract)
|
||||
static parser_status_t
|
||||
suunto_vyper_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
suunto_vyper_parser_t *parser = (suunto_vyper_parser_t *) abstract;
|
||||
|
||||
if (! parser_is_suunto_vyper (abstract))
|
||||
return PARSER_STATUS_TYPE_MISMATCH;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->divetime = 0;
|
||||
parser->maxdepth = 0;
|
||||
|
||||
return PARSER_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -123,6 +140,71 @@ suunto_vyper_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime)
|
||||
}
|
||||
|
||||
|
||||
static parser_status_t
|
||||
suunto_vyper_parser_get_field (parser_t *abstract, parser_field_type_t type, unsigned int flags, void *value)
|
||||
{
|
||||
suunto_vyper_parser_t *parser = (suunto_vyper_parser_t *) abstract;
|
||||
|
||||
const unsigned char *data = abstract->data;
|
||||
unsigned int size = abstract->size;
|
||||
|
||||
if (size < 18)
|
||||
return PARSER_STATUS_ERROR;
|
||||
|
||||
if (!parser->cached) {
|
||||
unsigned int interval = data[3];
|
||||
unsigned int nsamples = 0;
|
||||
unsigned int depth = 0, maxdepth = 0;
|
||||
unsigned int offset = 14;
|
||||
while (offset < size && data[offset] != 0x80) {
|
||||
unsigned char value = data[offset++];
|
||||
if (value < 0x79 || value > 0x87) {
|
||||
depth += (signed char) value;
|
||||
if (depth > maxdepth)
|
||||
maxdepth = depth;
|
||||
nsamples++;
|
||||
}
|
||||
}
|
||||
|
||||
// Store the offset to the end marker.
|
||||
unsigned int marker = offset;
|
||||
if (marker + 4 >= size || data[marker] != 0x80)
|
||||
return PARSER_STATUS_ERROR;
|
||||
|
||||
parser->cached = 1;
|
||||
parser->divetime = nsamples * interval;
|
||||
parser->maxdepth = maxdepth;
|
||||
}
|
||||
|
||||
gasmix_t *gas = (gasmix_t *) value;
|
||||
|
||||
if (value) {
|
||||
switch (type) {
|
||||
case FIELD_TYPE_DIVETIME:
|
||||
*((unsigned int *) value) = parser->divetime;
|
||||
break;
|
||||
case FIELD_TYPE_MAXDEPTH:
|
||||
*((double *) value) = parser->maxdepth * FEET;
|
||||
break;
|
||||
case FIELD_TYPE_GASMIX_COUNT:
|
||||
*((unsigned int *) value) = 1;
|
||||
break;
|
||||
case FIELD_TYPE_GASMIX:
|
||||
gas->helium = 0.0;
|
||||
if (data[6])
|
||||
gas->oxygen = data[6] / 100.0;
|
||||
else
|
||||
gas->oxygen = 0.21;
|
||||
gas->nitrogen = 1.0 - gas->oxygen;
|
||||
break;
|
||||
default:
|
||||
return PARSER_STATUS_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
return PARSER_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static parser_status_t
|
||||
suunto_vyper_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user