Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions include/libdivecomputer/suunto_nautic.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ extern "C" {
* "/System/Mode", "/Logbook/Entries") and return the raw, undecoded
* response payload (the ACK only).
*/
/*
* 1 when the watch answered the EVA handshake on open. The open still succeeds
* when only other frames arrived before the link went quiet (a sleeping watch
* or the tail of an earlier stream), so 0 means the first request may time out.
*/
int
suunto_nautic_device_handshake_acknowledged (dc_device_t *device);

dc_status_t
suunto_nautic_device_request (dc_device_t *device, const char *path, dc_buffer_t *response);

Expand Down
16 changes: 15 additions & 1 deletion src/suunto_nautic.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ typedef struct suunto_nautic_device_t {
// fingerprint set" (a real dive ID is never 0 -- that would be a
// 1970 timestamp), matching every other driver's convention.
unsigned char fingerprint[4];
// Whether the watch answered the EVA handshake; the open carries on without it.
int handshake_acknowledged;
} suunto_nautic_device_t;

static dc_status_t suunto_nautic_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
Expand Down Expand Up @@ -456,6 +458,7 @@ suunto_nautic_device_open (dc_device_t **out, dc_context_t *context, dc_iostream
if (device->sequence == 0)
device->sequence = 1;
memset (device->fingerprint, 0, sizeof (device->fingerprint));
device->handshake_acknowledged = 0;

status = dc_hdlc_open (&device->iostream, context, iostream, 244, 244);
if (status != DC_STATUS_SUCCESS) {
Expand Down Expand Up @@ -504,8 +507,10 @@ suunto_nautic_device_open (dc_device_t **out, dc_context_t *context, dc_iostream

HEXDUMP (context, DC_LOGLEVEL_DEBUG, "EVA RSP", handshake_rsp, handshake_len);

if (handshake_len >= 2 && handshake_rsp[0] == 0xA5 && handshake_rsp[1] == RPC_OP_HELLO_ACK)
if (handshake_len >= 2 && handshake_rsp[0] == 0xA5 && handshake_rsp[1] == RPC_OP_HELLO_ACK) {
device->handshake_acknowledged = 1;
break;
}
if (++handshake_skips >= MAX_FOREIGN_SKIPS) {
ERROR (context, "No EVA handshake response among the frames on the link.");
status = DC_STATUS_TIMEOUT;
Expand Down Expand Up @@ -535,6 +540,15 @@ suunto_nautic_device_close (dc_device_t *abstract)
return dc_iostream_close (device->iostream);
}

int
suunto_nautic_device_handshake_acknowledged (dc_device_t *abstract)
{
if (abstract == NULL || abstract->vtable->type != DC_FAMILY_SUUNTO_NAUTIC)
return 0;

return ((suunto_nautic_device_t *) abstract)->handshake_acknowledged;
}

dc_status_t
suunto_nautic_device_request (dc_device_t *abstract, const char *path, dc_buffer_t *response)
{
Expand Down
37 changes: 35 additions & 2 deletions src/suunto_nautic_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,13 @@
// (int32 LE, Pa). The end pressures are the app's; the start pressures keep a
// transmitter's pre-pairing dropout value (9 bar on 1788683271), so they aren't used.
#define SUMMARY_FOOTER_RECORD 1
// Records 2-4 are the Windows; each carries Temperature.Min/Max (float32 LE, K)
// in the order its schema gives, on both watches. The dive record's pair above is
// reversed by Ocean firmware, so the Windows are read first.
#define SUMMARY_WINDOW_FIRST 2
#define SUMMARY_WINDOW_COUNT 3
#define SUMMARY_WINDOW_TEMP_MIN 101
#define SUMMARY_WINDOW_TEMP_MAX 105
#define SUMMARY_FOOTER_GAS_BASE 282
#define SUMMARY_FOOTER_GAS_END1 29
#define SUMMARY_FOOTER_GAS_END2 37
Expand Down Expand Up @@ -351,6 +358,29 @@ suunto_nautic_summary_record (const unsigned char *sbem, size_t size, unsigned i
return NULL;
}

// Lowest minimum and highest maximum water temperature across the Windows records (K).
static int
suunto_nautic_summary_window_temperatures (const unsigned char *sbem, size_t size, double *tmin, double *tmax)
{
int found = 0;
for (unsigned int i = 0; i < SUMMARY_WINDOW_COUNT; i++) {
size_t length = 0;
const unsigned char *window = suunto_nautic_summary_record (sbem, size, SUMMARY_WINDOW_FIRST + i, &length);
if (window == NULL || length < SUMMARY_WINDOW_TEMP_MAX + 4)
continue;
double lo = array_float_le (window + SUMMARY_WINDOW_TEMP_MIN);
double hi = array_float_le (window + SUMMARY_WINDOW_TEMP_MAX);
if (!(lo > 250.0 && hi < 330.0 && lo <= hi))
continue;
if (!found || lo < *tmin)
*tmin = lo;
if (!found || hi > *tmax)
*tmax = hi;
found = 1;
}
return found;
}

// The /Summary's dive record: the last record long enough to hold its fields.
static const unsigned char *
suunto_nautic_summary_dive_record (const unsigned char *sbem, size_t size)
Expand Down Expand Up @@ -994,8 +1024,11 @@ suunto_nautic_parser_parse (dc_parser_t *abstract, dc_sample_callback_t callback
double avgdepth = array_float_le (record + SUMMARY_DIVE_AVGDEPTH);
if (avgdepth > 0.0 && avgdepth <= parser->maxdepth)
parser->avgdepth = avgdepth;
double tmin = array_float_le (record + SUMMARY_DIVE_TEMP_MIN);
double tmax = array_float_le (record + SUMMARY_DIVE_TEMP_MAX);
double tmin = 0.0, tmax = 0.0;
if (!suunto_nautic_summary_window_temperatures (sbem, sbem_size, &tmin, &tmax)) {
tmin = array_float_le (record + SUMMARY_DIVE_TEMP_MIN);
tmax = array_float_le (record + SUMMARY_DIVE_TEMP_MAX);
}
if (tmin > tmax) {
double t = tmin;
tmin = tmax;
Expand Down
Loading