From 170bc8b39ba062be66c238b89436077a9f89f089 Mon Sep 17 00:00:00 2001 From: Latisha Date: Mon, 12 Oct 2026 00:32:56 +0800 Subject: [PATCH] suunto_nautic: honour a cancel during a /Data stream, raise the page cap, order the temperature pair A long dive streams for minutes and the cancel callback was only checked before each request, so a stopped sync kept downloading. Check it between stream frames, and still stop the stream so the watch doesn't keep sending. MAX_PAGES 64 truncated a dive's Descriptors schema (about 97 pages); raise it to 512. The Ocean can store the /Summary temperature pair reversed (the app then shows Min 29.35, Max 18.85 C); order it instead of falling back to the sampled range. --- src/suunto_nautic.c | 17 +++++++++++++---- src/suunto_nautic_parser.c | 11 ++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/suunto_nautic.c b/src/suunto_nautic.c index 2df349c..531d183 100644 --- a/src/suunto_nautic.c +++ b/src/suunto_nautic.c @@ -127,9 +127,10 @@ // size = compressed /Data + /Summary data bytes, exactly. #define ENTRY_SIZE_OFFSET 16 -// Safety cap on paginated-fetch pages (a Summary is a handful of pages, and -// /Logbook/Entries one page per ~18 dives). -#define MAX_PAGES 64 +// Safety cap on paginated-fetch pages (a Summary is a handful of pages, +// /Logbook/Entries one page per ~18 dives, and a dive's Descriptors schema +// about 97). +#define MAX_PAGES 512 // The Suunto "MDS" chunk header wrapping each compressed block: 28 bytes, // with the true payload size as a u16 LE at offset 20 and the compressed @@ -718,8 +719,16 @@ suunto_nautic_device_stream_fetch (dc_device_t *abstract, const char *path, dc_b goto release; } + // A long dive streams for minutes, so a cancel is honoured between frames; + // the stream is still stopped below so the watch doesn't keep sending it. + unsigned int cancelled = 0; unsigned int nframes = 0; for (nframes = 0; nframes < MAX_CHUNKS; nframes++) { + if (device_is_cancelled (abstract)) { + cancelled = 1; + break; + } + unsigned char packet[MAX_PACKET] = {0}; size_t len = 0; status = dc_iostream_read (device->iostream, packet, sizeof (packet), &len); @@ -753,7 +762,7 @@ suunto_nautic_device_stream_fetch (dc_device_t *abstract, const char *path, dc_b return status; } } - status = DC_STATUS_SUCCESS; + status = cancelled ? DC_STATUS_CANCELLED : DC_STATUS_SUCCESS; if (nframes >= MAX_CHUNKS) WARNING (abstract->context, "Stream for %s hit the %u-frame guard; the dive may be truncated.", path, MAX_CHUNKS); diff --git a/src/suunto_nautic_parser.c b/src/suunto_nautic_parser.c index c9eb8de..634417f 100644 --- a/src/suunto_nautic_parser.c +++ b/src/suunto_nautic_parser.c @@ -979,8 +979,8 @@ suunto_nautic_parser_parse (dc_parser_t *abstract, dc_sample_callback_t callback // it). Trusted only on a record whose dive time agrees with the // profile's, and when it is close to the sampled maximum. The same // record's average depth and water temperature range are the app's - // figures too; the temperatures are taken only as a sane pair, since - // one Ocean dive records its minimum above its maximum. + // figures too. The Ocean can store the temperature pair reversed (the + // app then shows Min 29.35 and Max 18.85 C), so it is ordered here. const unsigned char *record = suunto_nautic_summary_dive_record (sbem, sbem_size); if (record && parser->divetime > 0) { double divetime = array_float_le (record + SUMMARY_DIVE_DIVETIME); @@ -996,7 +996,12 @@ suunto_nautic_parser_parse (dc_parser_t *abstract, dc_sample_callback_t callback parser->avgdepth = avgdepth; double tmin = array_float_le (record + SUMMARY_DIVE_TEMP_MIN); double tmax = array_float_le (record + SUMMARY_DIVE_TEMP_MAX); - if (have_temperature && tmin > 250.0 && tmax < 330.0 && tmin <= tmax) { + if (tmin > tmax) { + double t = tmin; + tmin = tmax; + tmax = t; + } + if (have_temperature && tmin > 250.0 && tmax < 330.0) { parser->temperature_minimum = tmin - 273.15; parser->temperature_maximum = tmax - 273.15; }