diff --git a/src/libdivecomputer.symbols b/src/libdivecomputer.symbols index 9b68301..3a05a1e 100644 --- a/src/libdivecomputer.symbols +++ b/src/libdivecomputer.symbols @@ -39,6 +39,7 @@ oceanic_vtpro_device_open oceanic_vtpro_device_keepalive oceanic_vtpro_device_calibrate reefnet_sensus_device_open +reefnet_sensus_extract_dives reefnet_sensuspro_device_open reefnet_sensuspro_device_set_timestamp reefnet_sensuspro_device_write_interval diff --git a/src/reefnet_sensus.c b/src/reefnet_sensus.c index 02d7ed5..44b135e 100644 --- a/src/reefnet_sensus.c +++ b/src/reefnet_sensus.c @@ -21,6 +21,7 @@ #include // memcmp, memcpy #include // malloc, free +#include // assert #include "device-private.h" #include "reefnet_sensus.h" @@ -49,6 +50,7 @@ struct reefnet_sensus_device_t { static device_status_t reefnet_sensus_device_handshake (device_t *abstract, unsigned char *data, unsigned int size); static device_status_t reefnet_sensus_device_dump (device_t *abstract, unsigned char *data, unsigned int size, unsigned int *result); +static device_status_t reefnet_sensus_device_foreach (device_t *abstract, dive_callback_t callback, void *userdata); static device_status_t reefnet_sensus_device_close (device_t *abstract); static const device_backend_t reefnet_sensus_device_backend = { @@ -58,7 +60,7 @@ static const device_backend_t reefnet_sensus_device_backend = { NULL, /* read */ NULL, /* write */ reefnet_sensus_device_dump, /* dump */ - NULL, /* foreach */ + reefnet_sensus_device_foreach, /* foreach */ reefnet_sensus_device_close /* close */ }; @@ -306,3 +308,81 @@ reefnet_sensus_device_dump (device_t *abstract, unsigned char *data, unsigned in return DEVICE_STATUS_SUCCESS; } + + +static device_status_t +reefnet_sensus_device_foreach (device_t *abstract, dive_callback_t callback, void *userdata) +{ + reefnet_sensus_device_t *device = (reefnet_sensus_device_t*) abstract; + + if (! device_is_reefnet_sensus (abstract)) + return DEVICE_STATUS_TYPE_MISMATCH; + + unsigned char data[REEFNET_SENSUS_MEMORY_SIZE] = {0}; + + device_status_t rc = reefnet_sensus_device_dump (abstract, data, sizeof (data), NULL); + if (rc != DEVICE_STATUS_SUCCESS) + return rc; + + return reefnet_sensus_extract_dives (data, sizeof (data), callback, userdata); +} + + +device_status_t +reefnet_sensus_extract_dives (const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata) +{ + // Search the entire data stream for start markers. + unsigned int previous = size; + unsigned int current = (size >= 7 ? size - 7 : 0); + while (current > 0) { + current--; + if (data[current] == 0xFF && data[current + 6] == 0xFE) { + // Once a start marker is found, start searching + // for the end of the dive. The search is now + // limited to the start of the previous dive. + int found = 0; + unsigned int nsamples = 0, count = 0; + unsigned int offset = current + 7; // Skip non-sample data. + while (offset + 1 <= previous) { + // Depth (adjusted feet of seawater). + unsigned char depth = data[offset++]; + + // Temperature (degrees Fahrenheit) + if ((nsamples % 6) == 0) { + assert (offset + 1 <= previous); + offset++; + } + + // Current sample is complete. + nsamples++; + + // The end of a dive is reached when 17 consecutive + // depth samples of less than 3 feet have been found. + if (depth < 13 + 3) { + count++; + if (count == 17) { + found = 1; + break; + } + } else { + count = 0; + } + } + + // Report an error if no end of dive was found. + if (!found) { + WARNING ("No end of dive found."); + return DEVICE_STATUS_ERROR; + } + + if (callback && !callback (data + current, offset - current, userdata)) + return DEVICE_STATUS_SUCCESS; + + // Prepare for the next dive. + previous = current; + current = (current >= 7 ? current - 7 : 0); + } + } + + return DEVICE_STATUS_SUCCESS; +} diff --git a/src/reefnet_sensus.h b/src/reefnet_sensus.h index a6c3b05..8f3c438 100644 --- a/src/reefnet_sensus.h +++ b/src/reefnet_sensus.h @@ -34,6 +34,9 @@ extern "C" { device_status_t reefnet_sensus_device_open (device_t **device, const char* name); +device_status_t +reefnet_sensus_extract_dives (const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata); + #ifdef __cplusplus } #endif /* __cplusplus */