From 2106cb2dabe58741e32572055276259b8ae9eb95 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Tue, 13 Oct 2015 19:21:56 -0700 Subject: [PATCH] Add tank size reporting for Suunto EON Steel Sadly the data we get from the EON Steel is a bit of a mess. It doesn't really tell us if the data is metric or imperial (it always sends both wet volume and working pressure). And in imperial mode the Suunto engineers seem a bit confused. The pressure given (entered on the dive computer in psi) is sent to us not in bar, not in atm... it's "something". As far as I can tell it's a constant factor of 1.00069182389937 different from bar. And the wet sizes are a bit to small to get the cuft size the user entered. But instead of trying to guess and fix the mess, we just pass it through... So this is somewhat useful, but not really what most users will want. Linus started this commit with a few lines that parsed the right values out of the data stream from the Suunto EON Steel. I then added the implementation of the infrastructure to convert the raw data and report it back to the caller. Signed-off-by: Dirk Hohndel --- src/suunto_eonsteel_parser.c | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/suunto_eonsteel_parser.c b/src/suunto_eonsteel_parser.c index 86a60c4..f770dad 100644 --- a/src/suunto_eonsteel_parser.c +++ b/src/suunto_eonsteel_parser.c @@ -90,6 +90,8 @@ typedef struct suunto_eonsteel_parser_t { dc_salinity_t salinity; double surface_pressure; dc_field_string_t strings[MAXSTRINGS]; + double tanksize[MAXGASES]; + double tankworkingpressure[MAXGASES]; } cache; } suunto_eonsteel_parser_t; @@ -898,6 +900,8 @@ static dc_status_t get_string_field(suunto_eonsteel_parser_t *eon, unsigned idx, static dc_status_t suunto_eonsteel_parser_get_field(dc_parser_t *parser, dc_field_type_t type, unsigned int flags, void *value) { + dc_tank_t *tank = (dc_tank_t *) value; + suunto_eonsteel_parser_t *eon = (suunto_eonsteel_parser_t *)parser; if (!(eon->cache.initialized >> type)) @@ -914,6 +918,7 @@ suunto_eonsteel_parser_get_field(dc_parser_t *parser, dc_field_type_t type, unsi field_value(value, eon->cache.avgdepth); break; case DC_FIELD_GASMIX_COUNT: + case DC_FIELD_TANK_COUNT: field_value(value, eon->cache.ngases); break; case DC_FIELD_GASMIX: @@ -927,6 +932,22 @@ suunto_eonsteel_parser_get_field(dc_parser_t *parser, dc_field_type_t type, unsi case DC_FIELD_ATMOSPHERIC: field_value(value, eon->cache.surface_pressure); break; + case DC_FIELD_TANK: + /* Sadly it seems that the EON Steel doesn't tell us whether we get imperial + * or metric data - the only indication is metric is always whole liters */ + tank->volume = eon->cache.tanksize[flags]; + if (eon->cache.tanksize[flags] - (int)eon->cache.tanksize[flags] < 0.001) { + tank->type = DC_TANKVOLUME_METRIC; + tank->workpressure = 0; + } else { + /* the pressure reported is NOT the pressure the user enters. + * So 3000psi turns into 206.700 bar instead of 206.843 bar; + * We report it as we get it and let the application figure out + * what to do with that */ + tank->type = DC_TANKVOLUME_IMPERIAL; + tank->workpressure = eon->cache.tankworkingpressure[flags]; + } + break; case DC_FIELD_STRING: return get_string_field(eon, flags, (dc_field_string_t *)value); default: @@ -1004,6 +1025,22 @@ static int add_gas_he(suunto_eonsteel_parser_t *eon, unsigned char he) return 0; } +static int add_gas_size(suunto_eonsteel_parser_t *eon, float l) +{ + int idx = eon->cache.ngases-1; + if (idx >= 0) + eon->cache.tanksize[idx] = l; + return 0; +} + +static int add_gas_workpressure(suunto_eonsteel_parser_t *eon, float wp) +{ + int idx = eon->cache.ngases-1; + if (idx >= 0) + eon->cache.tankworkingpressure[idx] = wp; + return 0; +} + static int add_string(suunto_eonsteel_parser_t *eon, const char *desc, const char *value) { int i; @@ -1115,6 +1152,12 @@ static int traverse_diving_fields(suunto_eonsteel_parser_t *eon, const struct ty if (!strcmp(name, "Gases.Gas.TransmitterID")) return add_string(eon, "Transmitter ID", data); + if (!strcmp(name, "Gases.Gas.TankSize")) + return add_gas_size(eon, get_le32_float(data)); + + if (!strcmp(name, "Gases.Gas.TankFillPressure")) + return add_gas_workpressure(eon, get_le32_float(data)); + if (!strcmp(name, "SurfacePressure")) { unsigned int pressure = array_uint32_le(data); // in SI units - Pascal eon->cache.surface_pressure = pressure / 100000.0; // bar