Oceans S1: actually download all dives and parse them
This isn't perfect - we don't do the whole dive fingerprint etc, so right now it always downloads all dives. To make matters worse, it downloads dives oldest first, which then confuses the subsurface downloader that expects newest first. So there's stuff to clean up, but the basic profile data is all there. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
91658dd167
commit
da8ae52b50
107
src/oceans_s1.c
107
src/oceans_s1.c
@ -167,7 +167,7 @@ static dc_status_t oceans_s1_get_sequence(oceans_s1_device_t *s1, unsigned char
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t oceans_s1_get_blob(oceans_s1_device_t *s1, unsigned char **result)
|
||||
static dc_status_t oceans_s1_get_blob(oceans_s1_device_t *s1, const unsigned char **result)
|
||||
{
|
||||
dc_status_t status;
|
||||
dc_buffer_t *res;
|
||||
@ -441,7 +441,7 @@ oceans_s1_device_set_fingerprint(dc_device_t *abstract, const unsigned char data
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
get_dive_list(oceans_s1_device_t *s1, unsigned char **list)
|
||||
get_dive_list(oceans_s1_device_t *s1, const unsigned char **list)
|
||||
{
|
||||
dc_status_t status;
|
||||
|
||||
@ -457,7 +457,7 @@ get_dive_list(oceans_s1_device_t *s1, unsigned char **list)
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
get_one_dive(oceans_s1_device_t *s1, int nr, unsigned char **dive)
|
||||
get_one_dive(oceans_s1_device_t *s1, int nr, const unsigned char **dive)
|
||||
{
|
||||
dc_status_t status;
|
||||
|
||||
@ -472,10 +472,52 @@ get_one_dive(oceans_s1_device_t *s1, int nr, unsigned char **dive)
|
||||
return oceans_s1_get_blob(s1, dive);
|
||||
}
|
||||
|
||||
static const unsigned char *get_string_line(const unsigned char *in, const unsigned char **next)
|
||||
{
|
||||
const unsigned char *line;
|
||||
unsigned char c;
|
||||
|
||||
if (!in) {
|
||||
*next = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (isspace(*in))
|
||||
in++;
|
||||
|
||||
if (!*in) {
|
||||
*next = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
line = in;
|
||||
while ((c = *in) != 0) {
|
||||
if (c == '\r' || c == '\n')
|
||||
break;
|
||||
in++;
|
||||
}
|
||||
*next = in;
|
||||
return line;
|
||||
}
|
||||
|
||||
static int count_dives(const unsigned char *divelist)
|
||||
{
|
||||
int dives = 0;
|
||||
const unsigned char *line;
|
||||
|
||||
while ((line = get_string_line(divelist, &divelist)) != NULL) {
|
||||
if (strncmp(line, "dive ", 5))
|
||||
continue;
|
||||
dives++;
|
||||
}
|
||||
return dives;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
oceans_s1_device_foreach(dc_device_t *abstract, dc_dive_callback_t callback, void *userdata)
|
||||
{
|
||||
unsigned char *divelist, *dive;
|
||||
int nr;
|
||||
const unsigned char *divelist, *line;
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
oceans_s1_device_t *s1 = (oceans_s1_device_t*)abstract;
|
||||
|
||||
@ -485,19 +527,60 @@ oceans_s1_device_foreach(dc_device_t *abstract, dc_dive_callback_t callback, voi
|
||||
status = get_dive_list(s1, &divelist);
|
||||
if (status != DC_STATUS_SUCCESS)
|
||||
return status;
|
||||
fprintf(stderr, "divelist = %s\n", divelist);
|
||||
|
||||
nr = count_dives(divelist);
|
||||
if (!nr)
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
progress.current = 0;
|
||||
progress.maximum = 100;
|
||||
progress.maximum = nr;
|
||||
device_event_emit(abstract, DC_EVENT_PROGRESS, &progress);
|
||||
|
||||
// Just force dive 4 for now
|
||||
status = get_one_dive(s1, 4, &dive);
|
||||
if (status != DC_STATUS_SUCCESS)
|
||||
return status;
|
||||
fprintf(stderr, "dive 4 = %s\n", dive);
|
||||
int dive_nr = 0, dive_unknown = 0, dive_o2 = 0;
|
||||
int dive_depth, dive_time;
|
||||
long long dive_date = -1;
|
||||
char fingerprint[32];
|
||||
|
||||
// Fill in
|
||||
while ((line = get_string_line(divelist, &divelist)) != NULL) {
|
||||
int linelen = divelist - line;
|
||||
const unsigned char *dive;
|
||||
|
||||
/* We only care about 'dive' and 'enddive' lines */
|
||||
if (linelen < 8 || linelen >= 32)
|
||||
continue;
|
||||
|
||||
if (!memcmp(line, "dive ", 5)) {
|
||||
int nr, unknown, o2;
|
||||
long long date;
|
||||
|
||||
if (sscanf(line, "dive %d,%d,%d,%lld", &nr, &unknown, &o2, &date) != 4)
|
||||
continue;
|
||||
dive_nr = nr;
|
||||
dive_unknown = unknown;
|
||||
dive_o2 = o2;
|
||||
dive_date = date;
|
||||
|
||||
memset(fingerprint, 0, sizeof(fingerprint));
|
||||
memcpy(fingerprint, line, linelen);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (memcmp(line, "enddive ", 8))
|
||||
continue;
|
||||
|
||||
if (sscanf(line, "enddive %d,%d", &dive_depth, &dive_time) != 2)
|
||||
continue;
|
||||
|
||||
status = get_one_dive(s1, dive_nr, &dive);
|
||||
if (status != DC_STATUS_SUCCESS)
|
||||
return status;
|
||||
|
||||
progress.current++;
|
||||
device_event_emit(abstract, DC_EVENT_PROGRESS, &progress);
|
||||
|
||||
if (callback && !callback(dive, strlen(dive), fingerprint, sizeof(fingerprint), userdata))
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "oceans_s1.h"
|
||||
#include "context-private.h"
|
||||
@ -16,6 +18,9 @@ typedef struct oceans_s1_parser_t oceans_s1_parser_t;
|
||||
|
||||
struct oceans_s1_parser_t {
|
||||
dc_parser_t base;
|
||||
int divenr;
|
||||
unsigned int maxdepth, duration;
|
||||
long long date;
|
||||
struct dc_field_cache cache;
|
||||
};
|
||||
|
||||
@ -37,7 +42,7 @@ static const dc_parser_vtable_t oceans_s1_parser_vtable = {
|
||||
dc_status_t
|
||||
oceans_s1_parser_create(dc_parser_t **out, dc_context_t *context)
|
||||
{
|
||||
oceans_s1_parser_t* parser = NULL;
|
||||
oceans_s1_parser_t *parser = NULL;
|
||||
|
||||
if (out == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
@ -54,23 +59,139 @@ oceans_s1_parser_create(dc_parser_t **out, dc_context_t *context)
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static const unsigned char *get_string_line(const unsigned char *in, const unsigned char **next)
|
||||
{
|
||||
const unsigned char *line;
|
||||
unsigned char c;
|
||||
|
||||
if (!in) {
|
||||
*next = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (isspace(*in))
|
||||
in++;
|
||||
|
||||
if (!*in) {
|
||||
*next = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
line = in;
|
||||
while ((c = *in) != 0) {
|
||||
if (c == '\r' || c == '\n')
|
||||
break;
|
||||
in++;
|
||||
}
|
||||
*next = in;
|
||||
return line;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
oceans_s1_parse_dive(struct oceans_s1_parser_t *s1, const unsigned char *data, dc_sample_callback_t callback, void *userdata)
|
||||
{
|
||||
const unsigned char *line;
|
||||
unsigned int sample_interval = 10;
|
||||
unsigned int sample_time = 0;
|
||||
|
||||
memset(&s1->cache, 0, sizeof(s1->cache));
|
||||
|
||||
while ((line = get_string_line(data, &data)) != NULL) {
|
||||
dc_sample_value_t sample = {0};
|
||||
int depth = 0, temp = 0, flags = 0;
|
||||
|
||||
if (!strncmp(line, "divelog ", 8)) {
|
||||
sscanf(line, "divelog v1,%us/sample", &sample_interval);
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(line, "dive ", 5)) {
|
||||
int nr, unknown, o2;
|
||||
long long date;
|
||||
|
||||
sscanf(line, "dive %d,%d,%d,%lld", &nr, &unknown, &o2, &date);
|
||||
s1->divenr = nr;
|
||||
s1->date = date;
|
||||
// I think "unknown" is dive mode
|
||||
if (o2) {
|
||||
dc_gasmix_t mix = { 0 };
|
||||
mix.oxygen = o2 / 100.0;
|
||||
DC_ASSIGN_FIELD(s1->cache, GASMIX_COUNT, 1);
|
||||
DC_ASSIGN_IDX(s1->cache, GASMIX, 0, mix);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(line, "continue ", 9)) {
|
||||
int depth = 0, seconds = 0;
|
||||
sscanf(line, "continue %d,%d", &depth, &seconds);
|
||||
|
||||
// Create surface samples for the surface time,
|
||||
// and then a depth sample at the stated depth
|
||||
if (callback) {
|
||||
if (seconds >= sample_interval*2) {
|
||||
dc_sample_value_t sample = {0};
|
||||
sample.time = sample_time + sample_interval;
|
||||
callback(DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.depth = 0;
|
||||
callback(DC_SAMPLE_DEPTH, sample, userdata);
|
||||
|
||||
sample.time = sample_time + seconds - sample_interval;
|
||||
callback(DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.depth = 0;
|
||||
callback(DC_SAMPLE_DEPTH, sample, userdata);
|
||||
}
|
||||
sample.time = sample_time + seconds;
|
||||
callback(DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.depth = depth / 100.0;
|
||||
callback(DC_SAMPLE_DEPTH, sample, userdata);
|
||||
}
|
||||
sample_time += seconds;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(line, "enddive ", 8)) {
|
||||
int maxdepth = 0, duration = 0;
|
||||
sscanf(line, "enddive %d,%d", &maxdepth, &duration);
|
||||
DC_ASSIGN_FIELD(s1->cache, MAXDEPTH, maxdepth / 100.0);
|
||||
DC_ASSIGN_FIELD(s1->cache, DIVETIME, duration);
|
||||
s1->maxdepth = maxdepth;
|
||||
s1->duration = duration;
|
||||
continue;
|
||||
}
|
||||
if (sscanf(line, "%d,%d,%d", &depth, &temp, &flags) != 3)
|
||||
continue;
|
||||
|
||||
sample_time += sample_interval;
|
||||
if (callback) {
|
||||
dc_sample_value_t sample = {0};
|
||||
sample.time = sample_time;
|
||||
callback(DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.depth = depth / 100.0;
|
||||
callback(DC_SAMPLE_DEPTH, sample, userdata);
|
||||
sample.temperature = temp;
|
||||
callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
}
|
||||
}
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
oceans_s1_parser_set_data(dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
// Fill me
|
||||
return DC_STATUS_SUCCESS;
|
||||
struct oceans_s1_parser_t *s1 = (struct oceans_s1_parser_t *)abstract;
|
||||
|
||||
return oceans_s1_parse_dive(s1, data, NULL, NULL);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
oceans_s1_parser_get_datetime(dc_parser_t* abstract, dc_datetime_t* datetime)
|
||||
oceans_s1_parser_get_datetime(dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
// Fill me
|
||||
oceans_s1_parser_t *s1 = (oceans_s1_parser_t *)abstract;
|
||||
|
||||
dc_datetime_gmtime(datetime, s1->date);
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
oceans_s1_parser_get_field(dc_parser_t* abstract, dc_field_type_t type, unsigned int flags, void* value)
|
||||
oceans_s1_parser_get_field(dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value)
|
||||
{
|
||||
oceans_s1_parser_t *s1 = (oceans_s1_parser_t *)abstract;
|
||||
|
||||
@ -78,8 +199,9 @@ oceans_s1_parser_get_field(dc_parser_t* abstract, dc_field_type_t type, unsigned
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
oceans_s1_parser_samples_foreach(dc_parser_t* abstract, dc_sample_callback_t callback, void* userdata)
|
||||
oceans_s1_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
|
||||
{
|
||||
// Fill me
|
||||
return DC_STATUS_SUCCESS;
|
||||
struct oceans_s1_parser_t *s1 = (struct oceans_s1_parser_t *)abstract;
|
||||
|
||||
return oceans_s1_parse_dive(s1, s1->base.data, callback, userdata);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user