Garmin: Fixes to Add Support .fit format version 2.1.
Ignore timestamps on messages that we do not read any other fields from - with the new (firmware >= 16.x) .fit file format these messages seem to be sent out of order, causing other messages to be ignored if they come after them in the file but are before them in the timeline. Track the OC / CCR state at the beginning of the dive based on the dive type - this avoids spurious 'switched to ...' messages caused by new 'gas switch' messages at the beginning of dives. See also https://forums.garmin.com/developer/fit-sdk/b/news-announcements/posts/important-fit-activity-file-message-change Signed-off-by: Michael Keller <github@ike.ch>
This commit is contained in:
parent
792090566e
commit
bb502c6d8b
@ -129,7 +129,7 @@ typedef struct garmin_parser_t {
|
||||
unsigned int setpoint_low_cbar, setpoint_high_cbar;
|
||||
unsigned int setpoint_low_switch_depth_mm, setpoint_high_switch_depth_mm;
|
||||
unsigned int setpoint_low_switch_mode, setpoint_high_switch_mode;
|
||||
dc_gasmix_t *current_gasmix;
|
||||
dc_usage_t current_gasmix_usage;
|
||||
} dive;
|
||||
|
||||
// I count nine (!) different GPS fields Hmm.
|
||||
@ -239,11 +239,11 @@ static void garmin_event(struct garmin_parser_t *garmin,
|
||||
sample.gasmix = data;
|
||||
garmin->callback(DC_SAMPLE_GASMIX, &sample, garmin->userdata);
|
||||
|
||||
dc_gasmix_t *gasmix = &garmin->cache.GASMIX[data];
|
||||
if (!garmin->dive.current_gasmix || gasmix->usage != garmin->dive.current_gasmix->usage) {
|
||||
dc_usage_t gasmix_usage = garmin->cache.GASMIX[data].usage;
|
||||
if (gasmix_usage != garmin->dive.current_gasmix_usage) {
|
||||
dc_sample_value_t sample2 = {0};
|
||||
sample2.event.type = SAMPLE_EVENT_STRING;
|
||||
if (gasmix->usage == DC_USAGE_DILUENT) {
|
||||
if (gasmix_usage == DC_USAGE_DILUENT) {
|
||||
sample2.event.name = "Switched to closed circuit";
|
||||
} else {
|
||||
sample2.event.name = "Switched to open circuit bailout";
|
||||
@ -252,7 +252,7 @@ static void garmin_event(struct garmin_parser_t *garmin,
|
||||
|
||||
garmin->callback(DC_SAMPLE_EVENT, &sample2, garmin->userdata);
|
||||
|
||||
garmin->dive.current_gasmix = gasmix;
|
||||
garmin->dive.current_gasmix_usage = gasmix_usage;
|
||||
}
|
||||
|
||||
return;
|
||||
@ -486,19 +486,22 @@ DECLARE_FIELD(ANY, timestamp, UINT32)
|
||||
{
|
||||
garmin->record_data.timestamp = data;
|
||||
if (garmin->callback) {
|
||||
dc_sample_value_t sample = {0};
|
||||
|
||||
// Turn the timestamp relative to the beginning of the dive
|
||||
if (data < garmin->dive.time)
|
||||
if (data < garmin->dive.time) {
|
||||
DEBUG(garmin->base.context, "Timestamp before dive start: %d (dive start: %d)", data, garmin->dive.time);
|
||||
|
||||
return;
|
||||
data -= garmin->dive.time;
|
||||
}
|
||||
data -= garmin->dive.time - 1;
|
||||
|
||||
// Did we already do this?
|
||||
if (data < garmin->record_data.time)
|
||||
if (data == garmin->record_data.time)
|
||||
return;
|
||||
|
||||
garmin->record_data.time = data;
|
||||
|
||||
// Now we're ready to actually update the sample times
|
||||
garmin->record_data.time = data+1;
|
||||
dc_sample_value_t sample = {0};
|
||||
sample.time = data * 1000;
|
||||
garmin->callback(DC_SAMPLE_TIME, &sample, garmin->userdata);
|
||||
}
|
||||
@ -656,6 +659,7 @@ DECLARE_FIELD(ACTIVITY, event_group, UINT8) { }
|
||||
// SPORT
|
||||
DECLARE_FIELD(SPORT, sub_sport, ENUM) {
|
||||
garmin->dive.sub_sport = (ENUM) data;
|
||||
garmin->dive.current_gasmix_usage = DC_USAGE_OPEN_CIRCUIT;
|
||||
dc_divemode_t val;
|
||||
switch (data) {
|
||||
case 55: val = DC_DIVEMODE_GAUGE;
|
||||
@ -663,7 +667,10 @@ DECLARE_FIELD(SPORT, sub_sport, ENUM) {
|
||||
case 56:
|
||||
case 57: val = DC_DIVEMODE_FREEDIVE;
|
||||
break;
|
||||
case 63: val = DC_DIVEMODE_CCR;
|
||||
case 63:
|
||||
val = DC_DIVEMODE_CCR;
|
||||
garmin->dive.current_gasmix_usage = DC_USAGE_DILUENT;
|
||||
|
||||
break;
|
||||
default: val = DC_DIVEMODE_OC;
|
||||
}
|
||||
@ -1337,7 +1344,10 @@ static int traverse_regular(struct garmin_parser_t *garmin,
|
||||
}
|
||||
|
||||
if (field_desc) {
|
||||
field_desc->parse(garmin, base_type, data);
|
||||
if (field_nr == 253 && !msg_desc->maxfield)
|
||||
DEBUG(garmin->base.context, "Ignoring timestamp field for undefined message.");
|
||||
else
|
||||
field_desc->parse(garmin, base_type, data);
|
||||
} else {
|
||||
unknown_field(garmin, data, msg_name, field_nr, base_type, len);
|
||||
}
|
||||
@ -1521,7 +1531,12 @@ traverse_data(struct garmin_parser_t *garmin)
|
||||
// Compressed records are like normal records
|
||||
// with that added relative timestamp
|
||||
DEBUG(garmin->base.context, "Compressed record for type %d", type);
|
||||
parse_ANY_timestamp(garmin, time);
|
||||
|
||||
if (!(garmin->type_desc + type)->msg_desc->maxfield)
|
||||
DEBUG(garmin->base.context, "Ignoring timestamp field for undefined message.");
|
||||
else
|
||||
parse_ANY_timestamp(garmin, time);
|
||||
|
||||
len = traverse_regular(garmin, data, datasize, type, &time);
|
||||
} else if (record & 0x40) { // Definition record?
|
||||
len = traverse_definition(garmin, data, datasize, record);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user