2017-11-28 19:31:27 +00:00
// SPDX-License-Identifier: GPL-2.0
# ifdef __clang__
// Clang has a bug on zero-initialization of C structs.
# pragma clang diagnostic ignored "-Wmissing-field-initializers"
# endif
2018-05-22 07:07:42 +00:00
# include "ssrf.h"
2017-11-28 19:31:27 +00:00
# include "dive.h"
2020-10-25 12:28:55 +00:00
# include "sample.h"
2018-05-11 15:25:41 +00:00
# include "subsurface-string.h"
2017-11-28 19:31:27 +00:00
# include "parse.h"
# include "divelist.h"
# include "device.h"
# include "membuffer.h"
# include "gettext.h"
2020-10-25 13:10:52 +00:00
# include <stdlib.h>
2018-10-17 16:45:22 +00:00
static int shearwater_cylinders ( void * param , int columns , char * * data , char * * column )
2017-11-28 19:31:27 +00:00
{
2018-05-22 07:07:42 +00:00
UNUSED ( columns ) ;
UNUSED ( column ) ;
2018-10-17 16:45:22 +00:00
struct parser_state * state = ( struct parser_state * ) param ;
2019-08-04 16:44:57 +00:00
cylinder_t * cyl ;
2017-11-28 19:31:27 +00:00
int o2 = lrint ( strtod_flags ( data [ 0 ] , NULL , 0 ) * 1000 ) ;
int he = lrint ( strtod_flags ( data [ 1 ] , NULL , 0 ) * 1000 ) ;
/* Shearwater allows entering only 99%, not 100%
* so assume 99 % to be pure oxygen */
if ( o2 = = 990 & & he = = 0 )
o2 = 1000 ;
2019-08-04 16:59:14 +00:00
cyl = cylinder_start ( state ) ;
2019-08-04 16:44:57 +00:00
cyl - > gasmix . o2 . permille = o2 ;
cyl - > gasmix . he . permille = he ;
2018-10-17 16:45:22 +00:00
cylinder_end ( state ) ;
2017-11-28 19:31:27 +00:00
return 0 ;
}
2018-10-17 16:45:22 +00:00
static int shearwater_changes ( void * param , int columns , char * * data , char * * column )
2017-11-28 19:31:27 +00:00
{
2018-05-22 07:07:42 +00:00
UNUSED ( columns ) ;
UNUSED ( column ) ;
2018-10-17 16:45:22 +00:00
struct parser_state * state = ( struct parser_state * ) param ;
2019-08-04 16:44:57 +00:00
cylinder_t * cyl ;
2017-11-28 19:31:27 +00:00
if ( columns ! = 3 ) {
return 1 ;
}
if ( ! data [ 0 ] | | ! data [ 1 ] | | ! data [ 2 ] ) {
return 2 ;
}
int o2 = lrint ( strtod_flags ( data [ 1 ] , NULL , 0 ) * 1000 ) ;
int he = lrint ( strtod_flags ( data [ 2 ] , NULL , 0 ) * 1000 ) ;
/* Shearwater allows entering only 99%, not 100%
* so assume 99 % to be pure oxygen */
if ( o2 = = 990 & & he = = 0 )
o2 = 1000 ;
// Find the cylinder index
2020-09-12 18:17:18 +00:00
int index ;
2017-11-28 19:31:27 +00:00
bool found = false ;
2020-09-12 18:17:18 +00:00
for ( index = 0 ; index < state - > cur_dive - > cylinders . nr ; + + index ) {
const cylinder_t * cyl = get_cylinder ( state - > cur_dive , index ) ;
2019-08-04 16:44:57 +00:00
if ( cyl - > gasmix . o2 . permille = = o2 & & cyl - > gasmix . he . permille = = he ) {
2017-11-28 19:31:27 +00:00
found = true ;
break ;
}
}
if ( ! found ) {
// Cylinder not found, creating a new one
2019-08-04 16:59:14 +00:00
cyl = cylinder_start ( state ) ;
2019-08-04 16:44:57 +00:00
cyl - > gasmix . o2 . permille = o2 ;
cyl - > gasmix . he . permille = he ;
2018-10-17 16:45:22 +00:00
cylinder_end ( state ) ;
2017-11-28 19:31:27 +00:00
}
2020-09-12 18:17:18 +00:00
add_gas_switch_event ( state - > cur_dive , get_dc ( state ) , state - > sample_rate ? atoi ( data [ 0 ] ) / state - > sample_rate * 10 : atoi ( data [ 0 ] ) , index ) ;
2017-11-28 19:31:27 +00:00
return 0 ;
}
2018-10-17 16:45:22 +00:00
static int shearwater_profile_sample ( void * param , int columns , char * * data , char * * column )
2017-11-28 19:31:27 +00:00
{
2018-05-22 07:07:42 +00:00
UNUSED ( columns ) ;
UNUSED ( column ) ;
2018-10-17 16:45:22 +00:00
struct parser_state * state = ( struct parser_state * ) param ;
2018-05-27 13:56:09 +00:00
int d6 , d7 ;
2017-11-28 19:31:27 +00:00
2018-10-17 16:45:22 +00:00
sample_start ( state ) ;
2020-09-19 10:25:47 +00:00
/*
* If we have sample_rate , we use self calculated sample number
* to count the sample time .
* If we do not have sample_rate , we try to use the sample time
* provided by Shearwater as is .
*/
if ( data [ 9 ] & & state - > sample_rate )
state - > cur_sample - > time . seconds = atoi ( data [ 9 ] ) * state - > sample_rate ;
else if ( data [ 0 ] )
state - > cur_sample - > time . seconds = atoi ( data [ 0 ] ) ;
2017-11-28 19:31:27 +00:00
if ( data [ 1 ] )
2018-10-17 16:45:22 +00:00
state - > cur_sample - > depth . mm = state - > metric ? lrint ( strtod_flags ( data [ 1 ] , NULL , 0 ) * 1000 ) : feet_to_mm ( strtod_flags ( data [ 1 ] , NULL , 0 ) ) ;
2017-11-28 19:31:27 +00:00
if ( data [ 2 ] )
2018-10-17 16:45:22 +00:00
state - > cur_sample - > temperature . mkelvin = state - > metric ? C_to_mkelvin ( strtod_flags ( data [ 2 ] , NULL , 0 ) ) : F_to_mkelvin ( strtod_flags ( data [ 2 ] , NULL , 0 ) ) ;
2017-11-28 19:31:27 +00:00
if ( data [ 3 ] ) {
2018-10-17 16:45:22 +00:00
state - > cur_sample - > setpoint . mbar = lrint ( strtod_flags ( data [ 3 ] , NULL , 0 ) * 1000 ) ;
2017-11-28 19:31:27 +00:00
}
if ( data [ 4 ] )
2018-10-17 16:45:22 +00:00
state - > cur_sample - > ndl . seconds = atoi ( data [ 4 ] ) * 60 ;
2017-11-28 19:31:27 +00:00
if ( data [ 5 ] )
2018-10-17 16:45:22 +00:00
state - > cur_sample - > cns = atoi ( data [ 5 ] ) ;
2018-05-27 06:06:09 +00:00
if ( data [ 6 ] ) {
2018-05-27 13:56:09 +00:00
d6 = atoi ( data [ 6 ] ) ;
if ( d6 > 0 ) {
2018-10-17 16:45:22 +00:00
state - > cur_sample - > stopdepth . mm = state - > metric ? d6 * 1000 : feet_to_mm ( d6 ) ;
state - > cur_sample - > in_deco = 1 ;
2018-05-27 06:06:09 +00:00
} else if ( data [ 7 ] ) {
2018-05-27 13:56:09 +00:00
d7 = atoi ( data [ 7 ] ) ;
if ( d7 > 0 ) {
2018-10-17 16:45:22 +00:00
state - > cur_sample - > stopdepth . mm = state - > metric ? d7 * 1000 : feet_to_mm ( d7 ) ;
2018-05-27 14:17:15 +00:00
if ( data [ 8 ] )
2018-10-17 16:45:22 +00:00
state - > cur_sample - > stoptime . seconds = atoi ( data [ 8 ] ) * 60 ;
state - > cur_sample - > in_deco = 1 ;
2018-05-27 06:06:09 +00:00
} else {
2018-10-17 16:45:22 +00:00
state - > cur_sample - > in_deco = 0 ;
2018-05-27 06:06:09 +00:00
}
} else {
2018-10-17 16:45:22 +00:00
state - > cur_sample - > in_deco = 0 ;
2018-05-27 06:06:09 +00:00
}
}
2017-11-28 19:31:27 +00:00
/* We don't actually have data[3], but it should appear in the
* SQL query at some point .
if ( data [ 3 ] )
2018-10-17 16:45:22 +00:00
state - > cur_sample - > pressure [ 0 ] . mbar = state - > metric ? atoi ( data [ 3 ] ) * 1000 : psi_to_mbar ( atoi ( data [ 3 ] ) ) ;
2017-11-28 19:31:27 +00:00
*/
2018-10-17 16:45:22 +00:00
sample_end ( state ) ;
2017-11-28 19:31:27 +00:00
return 0 ;
}
2018-10-17 16:45:22 +00:00
static int shearwater_ai_profile_sample ( void * param , int columns , char * * data , char * * column )
2017-11-28 19:31:27 +00:00
{
2018-05-22 07:07:42 +00:00
UNUSED ( columns ) ;
UNUSED ( column ) ;
2018-10-17 16:45:22 +00:00
struct parser_state * state = ( struct parser_state * ) param ;
2018-05-27 13:56:09 +00:00
int d6 , d9 ;
2017-11-28 19:31:27 +00:00
2018-10-17 16:45:22 +00:00
sample_start ( state ) ;
2020-09-19 10:25:47 +00:00
/*
* If we have sample_rate , we use self calculated sample number
* to count the sample time .
* If we do not have sample_rate , we try to use the sample time
* provided by Shearwater as is .
*/
if ( data [ 11 ] & & state - > sample_rate )
state - > cur_sample - > time . seconds = atoi ( data [ 11 ] ) * state - > sample_rate ;
else if ( data [ 0 ] )
state - > cur_sample - > time . seconds = atoi ( data [ 0 ] ) ;
2017-11-28 19:31:27 +00:00
if ( data [ 1 ] )
2018-10-17 16:45:22 +00:00
state - > cur_sample - > depth . mm = state - > metric ? lrint ( strtod_flags ( data [ 1 ] , NULL , 0 ) * 1000 ) : feet_to_mm ( strtod_flags ( data [ 1 ] , NULL , 0 ) ) ;
2017-11-28 19:31:27 +00:00
if ( data [ 2 ] )
2018-10-17 16:45:22 +00:00
state - > cur_sample - > temperature . mkelvin = state - > metric ? C_to_mkelvin ( strtod_flags ( data [ 2 ] , NULL , 0 ) ) : F_to_mkelvin ( strtod_flags ( data [ 2 ] , NULL , 0 ) ) ;
2017-11-28 19:31:27 +00:00
if ( data [ 3 ] ) {
2018-10-17 16:45:22 +00:00
state - > cur_sample - > setpoint . mbar = lrint ( strtod_flags ( data [ 3 ] , NULL , 0 ) * 1000 ) ;
2017-11-28 19:31:27 +00:00
}
if ( data [ 4 ] )
2018-10-17 16:45:22 +00:00
state - > cur_sample - > ndl . seconds = atoi ( data [ 4 ] ) * 60 ;
2017-11-28 19:31:27 +00:00
if ( data [ 5 ] )
2018-10-17 16:45:22 +00:00
state - > cur_sample - > cns = atoi ( data [ 5 ] ) ;
2018-05-27 06:06:09 +00:00
if ( data [ 6 ] ) {
2018-05-27 13:56:09 +00:00
d6 = atoi ( data [ 6 ] ) ;
if ( d6 > 0 ) {
2018-10-17 16:45:22 +00:00
state - > cur_sample - > stopdepth . mm = state - > metric ? d6 * 1000 : feet_to_mm ( d6 ) ;
state - > cur_sample - > in_deco = 1 ;
2018-05-27 06:06:09 +00:00
} else if ( data [ 9 ] ) {
2018-05-27 13:56:09 +00:00
d9 = atoi ( data [ 9 ] ) ;
if ( d9 > 0 ) {
2018-10-17 16:45:22 +00:00
state - > cur_sample - > stopdepth . mm = state - > metric ? d9 * 1000 : feet_to_mm ( d9 ) ;
2018-05-27 14:17:15 +00:00
if ( data [ 10 ] )
2018-10-17 16:45:22 +00:00
state - > cur_sample - > stoptime . seconds = atoi ( data [ 10 ] ) * 60 ;
state - > cur_sample - > in_deco = 1 ;
2018-05-27 06:06:09 +00:00
} else {
2018-10-17 16:45:22 +00:00
state - > cur_sample - > in_deco = 0 ;
2018-05-27 06:06:09 +00:00
}
} else {
2018-10-17 16:45:22 +00:00
state - > cur_sample - > in_deco = 0 ;
2018-05-27 06:06:09 +00:00
}
}
2017-11-28 19:31:27 +00:00
2020-09-10 13:46:52 +00:00
/*
* I have seen sample log where the sample pressure had to be multiplied by 2. However ,
* currently this seems to be corrected in ShearWater , so we are no longer taking this into
* account .
*
* Also , missing values might be nowadays 8184 , even though an old log I have received has
* 8190. Thus discarding values over 8180 here .
*/
if ( data [ 7 ] & & atoi ( data [ 7 ] ) < 8180 ) {
state - > cur_sample - > pressure [ 0 ] . mbar = psi_to_mbar ( atoi ( data [ 7 ] ) ) ;
2017-11-28 19:31:27 +00:00
}
2020-09-10 13:46:52 +00:00
if ( data [ 8 ] & & atoi ( data [ 8 ] ) < 8180 )
state - > cur_sample - > pressure [ 1 ] . mbar = psi_to_mbar ( atoi ( data [ 8 ] ) ) ;
2018-10-17 16:45:22 +00:00
sample_end ( state ) ;
2017-11-28 19:31:27 +00:00
return 0 ;
}
2018-10-17 16:45:22 +00:00
static int shearwater_mode ( void * param , int columns , char * * data , char * * column )
2017-11-28 19:31:27 +00:00
{
2018-05-22 07:07:42 +00:00
UNUSED ( columns ) ;
UNUSED ( column ) ;
2018-10-17 16:45:22 +00:00
struct parser_state * state = ( struct parser_state * ) param ;
2017-11-28 19:31:27 +00:00
if ( data [ 0 ] )
2018-10-17 16:45:22 +00:00
state - > cur_dive - > dc . divemode = atoi ( data [ 0 ] ) = = 0 ? CCR : OC ;
2017-11-28 19:31:27 +00:00
return 0 ;
}
2018-10-17 16:45:22 +00:00
static int shearwater_dive ( void * param , int columns , char * * data , char * * column )
2017-11-28 19:31:27 +00:00
{
2018-05-22 07:07:42 +00:00
UNUSED ( columns ) ;
UNUSED ( column ) ;
2017-11-28 19:31:27 +00:00
int retval = 0 ;
2018-10-17 16:45:22 +00:00
struct parser_state * state = ( struct parser_state * ) param ;
sqlite3 * handle = state - > sql_handle ;
2018-12-29 19:31:12 +00:00
char get_profile_template [ ] = " select currentTime,currentDepth,waterTemp,averagePPO2,currentNdl,CNSPercent,decoCeiling,firstStopDepth,firstStopTime from dive_log_records where diveLogId=%ld " ;
char get_profile_template_ai [ ] = " select currentTime,currentDepth,waterTemp,averagePPO2,currentNdl,CNSPercent,decoCeiling,aiSensor0_PressurePSI,aiSensor1_PressurePSI,firstStopDepth,firstStopTime from dive_log_records where diveLogId = %ld " ;
char get_cylinder_template [ ] = " select fractionO2,fractionHe from dive_log_records where diveLogId = %ld group by fractionO2,fractionHe " ;
char get_changes_template [ ] = " select a.currentTime,a.fractionO2,a.fractionHe from dive_log_records as a,dive_log_records as b where (a.id - 1) = b.id and (a.fractionO2 != b.fractionO2 or a.fractionHe != b.fractionHe) and a.diveLogId=b.divelogId and a.diveLogId = %ld " ;
char get_mode_template [ ] = " select distinct currentCircuitSetting from dive_log_records where diveLogId = %ld " ;
2017-11-28 19:31:27 +00:00
char get_buffer [ 1024 ] ;
2018-10-17 16:45:22 +00:00
dive_start ( state ) ;
state - > cur_dive - > number = atoi ( data [ 0 ] ) ;
2017-11-28 19:31:27 +00:00
2018-10-17 16:45:22 +00:00
state - > cur_dive - > when = ( time_t ) ( atol ( data [ 1 ] ) ) ;
2017-11-28 19:31:27 +00:00
2018-12-29 19:31:12 +00:00
long int dive_id = atol ( data [ 11 ] ) ;
2017-11-28 19:31:27 +00:00
if ( data [ 2 ] )
2018-10-17 16:45:22 +00:00
add_dive_site ( data [ 2 ] , state - > cur_dive , state ) ;
2017-11-28 19:31:27 +00:00
if ( data [ 3 ] )
2018-10-17 16:45:22 +00:00
utf8_string ( data [ 3 ] , & state - > cur_dive - > buddy ) ;
2017-11-28 19:31:27 +00:00
if ( data [ 4 ] )
2018-10-17 16:45:22 +00:00
utf8_string ( data [ 4 ] , & state - > cur_dive - > notes ) ;
2017-11-28 19:31:27 +00:00
2018-10-17 16:45:22 +00:00
state - > metric = atoi ( data [ 5 ] ) = = 1 ? 0 : 1 ;
2017-11-28 19:31:27 +00:00
/* TODO: verify that metric calculation is correct */
if ( data [ 6 ] )
2018-10-17 16:45:22 +00:00
state - > cur_dive - > dc . maxdepth . mm = state - > metric ? lrint ( strtod_flags ( data [ 6 ] , NULL , 0 ) * 1000 ) : feet_to_mm ( strtod_flags ( data [ 6 ] , NULL , 0 ) ) ;
2017-11-28 19:31:27 +00:00
if ( data [ 7 ] )
2018-10-17 16:45:22 +00:00
state - > cur_dive - > dc . duration . seconds = atoi ( data [ 7 ] ) * 60 ;
2017-11-28 19:31:27 +00:00
if ( data [ 8 ] )
2018-10-17 16:45:22 +00:00
state - > cur_dive - > dc . surface_pressure . mbar = atoi ( data [ 8 ] ) ;
2017-11-28 19:31:27 +00:00
/*
* TODO : the deviceid hash should be calculated here .
*/
2018-10-17 16:45:22 +00:00
settings_start ( state ) ;
dc_settings_start ( state ) ;
2017-11-28 19:31:27 +00:00
if ( data [ 9 ] )
2018-10-17 16:45:22 +00:00
utf8_string ( data [ 9 ] , & state - > cur_settings . dc . serial_nr ) ;
2017-11-28 19:31:27 +00:00
if ( data [ 10 ] ) {
switch ( atoi ( data [ 10 ] ) ) {
case 2 :
2018-10-17 16:45:22 +00:00
state - > cur_settings . dc . model = strdup ( " Shearwater Petrel/Perdix " ) ;
2017-11-28 19:31:27 +00:00
break ;
case 4 :
2018-10-17 16:45:22 +00:00
state - > cur_settings . dc . model = strdup ( " Shearwater Predator " ) ;
2017-11-28 19:31:27 +00:00
break ;
default :
2018-10-17 16:45:22 +00:00
state - > cur_settings . dc . model = strdup ( " Shearwater import " ) ;
2017-11-28 19:31:27 +00:00
break ;
}
}
2018-10-17 16:45:22 +00:00
state - > cur_settings . dc . deviceid = atoi ( data [ 9 ] ) ;
2017-11-28 19:31:27 +00:00
2018-10-17 16:45:22 +00:00
dc_settings_end ( state ) ;
settings_end ( state ) ;
2017-11-28 19:31:27 +00:00
if ( data [ 10 ] ) {
switch ( atoi ( data [ 10 ] ) ) {
case 2 :
2018-10-17 16:45:22 +00:00
state - > cur_dive - > dc . model = strdup ( " Shearwater Petrel/Perdix " ) ;
2017-11-28 19:31:27 +00:00
break ;
case 4 :
2018-10-17 16:45:22 +00:00
state - > cur_dive - > dc . model = strdup ( " Shearwater Predator " ) ;
2017-11-28 19:31:27 +00:00
break ;
default :
2018-10-17 16:45:22 +00:00
state - > cur_dive - > dc . model = strdup ( " Shearwater import " ) ;
2017-11-28 19:31:27 +00:00
break ;
}
}
if ( data [ 11 ] ) {
snprintf ( get_buffer , sizeof ( get_buffer ) - 1 , get_mode_template , dive_id ) ;
2019-10-26 21:11:44 +00:00
retval = sqlite3_exec ( handle , get_buffer , & shearwater_mode , state , NULL ) ;
2017-11-28 19:31:27 +00:00
if ( retval ! = SQLITE_OK ) {
fprintf ( stderr , " %s " , " Database query shearwater_mode failed. \n " ) ;
return 1 ;
}
}
snprintf ( get_buffer , sizeof ( get_buffer ) - 1 , get_cylinder_template , dive_id ) ;
2019-10-26 21:11:44 +00:00
retval = sqlite3_exec ( handle , get_buffer , & shearwater_cylinders , state , NULL ) ;
2017-11-28 19:31:27 +00:00
if ( retval ! = SQLITE_OK ) {
fprintf ( stderr , " %s " , " Database query shearwater_cylinders failed. \n " ) ;
return 1 ;
}
snprintf ( get_buffer , sizeof ( get_buffer ) - 1 , get_changes_template , dive_id ) ;
2019-10-26 21:11:44 +00:00
retval = sqlite3_exec ( handle , get_buffer , & shearwater_changes , state , NULL ) ;
2017-11-28 19:31:27 +00:00
if ( retval ! = SQLITE_OK ) {
fprintf ( stderr , " %s " , " Database query shearwater_changes failed. \n " ) ;
return 1 ;
}
snprintf ( get_buffer , sizeof ( get_buffer ) - 1 , get_profile_template_ai , dive_id ) ;
2019-10-26 21:11:44 +00:00
retval = sqlite3_exec ( handle , get_buffer , & shearwater_ai_profile_sample , state , NULL ) ;
2017-11-28 19:31:27 +00:00
if ( retval ! = SQLITE_OK ) {
snprintf ( get_buffer , sizeof ( get_buffer ) - 1 , get_profile_template , dive_id ) ;
2019-10-26 21:11:44 +00:00
retval = sqlite3_exec ( handle , get_buffer , & shearwater_profile_sample , state , NULL ) ;
2017-11-28 19:31:27 +00:00
if ( retval ! = SQLITE_OK ) {
fprintf ( stderr , " %s " , " Database query shearwater_profile_sample failed. \n " ) ;
return 1 ;
}
}
2018-10-17 16:45:22 +00:00
dive_end ( state ) ;
2017-11-28 19:31:27 +00:00
return SQLITE_OK ;
}
2018-12-29 19:32:55 +00:00
static int shearwater_cloud_dive ( void * param , int columns , char * * data , char * * column )
{
UNUSED ( columns ) ;
UNUSED ( column ) ;
int retval = 0 ;
struct parser_state * state = ( struct parser_state * ) param ;
sqlite3 * handle = state - > sql_handle ;
2020-09-19 10:25:47 +00:00
/*
* Since Shearwater reported sample time can be totally bogus ,
* we need to calculate the sample number by ourselves . The
* calculated sample number is multiplied by sample interval
* giving us correct sample time .
*/
char get_profile_template [ ] = " select currentTime,currentDepth,waterTemp,averagePPO2,currentNdl,CNSPercent,decoCeiling,firstStopDepth,firstStopTime,(select count(0) from dive_log_records r where r.id < d.id and r.diveLogId = %ld and r.currentTime > 0) as row from dive_log_records d where d.diveLogId=%ld and d.currentTime > 0 " ;
char get_profile_template_ai [ ] = " select currentTime,currentDepth,waterTemp,averagePPO2,currentNdl,CNSPercent,decoCeiling,aiSensor0_PressurePSI,aiSensor1_PressurePSI,firstStopDepth,firstStopTime,(select count(0) from dive_log_records r where r.id < d.id and r.diveLogId = %ld and r.currentTime > 0) as row from dive_log_records d where d.diveLogId = %ld and d.currentTime > 0 " ;
2018-12-29 19:32:55 +00:00
char get_cylinder_template [ ] = " select fractionO2 / 100,fractionHe / 100 from dive_log_records where diveLogId = %ld group by fractionO2,fractionHe " ;
2020-09-12 18:38:46 +00:00
char get_first_gas_template [ ] = " select currentTime, fractionO2 / 100, fractionHe / 100 from dive_log_records where diveLogId = %ld limit 1 " ;
2020-09-08 18:25:26 +00:00
char get_changes_template [ ] = " select a.currentTime,a.fractionO2 / 100,a.fractionHe /100 from dive_log_records as a,dive_log_records as b where (a.id - 1) = b.id and (a.fractionO2 != b.fractionO2 or a.fractionHe != b.fractionHe) and a.diveLogId=b.divelogId and a.diveLogId = %ld and a.fractionO2 > 0 and b.fractionO2 > 0 " ;
2018-12-29 19:32:55 +00:00
char get_mode_template [ ] = " select distinct currentCircuitSetting from dive_log_records where diveLogId = %ld " ;
char get_buffer [ 1024 ] ;
dive_start ( state ) ;
state - > cur_dive - > number = atoi ( data [ 0 ] ) ;
state - > cur_dive - > when = ( time_t ) ( atol ( data [ 1 ] ) ) ;
long int dive_id = atol ( data [ 11 ] ) ;
2018-12-29 20:31:52 +00:00
if ( data [ 12 ] )
2019-01-03 04:56:48 +00:00
state - > sample_rate = atoi ( data [ 12 ] ) ;
2018-12-29 20:31:52 +00:00
else
2019-01-03 04:56:48 +00:00
state - > sample_rate = 0 ;
2018-12-29 19:32:55 +00:00
if ( data [ 2 ] )
add_dive_site ( data [ 2 ] , state - > cur_dive , state ) ;
if ( data [ 3 ] )
utf8_string ( data [ 3 ] , & state - > cur_dive - > buddy ) ;
if ( data [ 4 ] )
utf8_string ( data [ 4 ] , & state - > cur_dive - > notes ) ;
state - > metric = atoi ( data [ 5 ] ) = = 1 ? 0 : 1 ;
/* TODO: verify that metric calculation is correct */
if ( data [ 6 ] )
state - > cur_dive - > dc . maxdepth . mm = state - > metric ? lrint ( strtod_flags ( data [ 6 ] , NULL , 0 ) * 1000 ) : feet_to_mm ( strtod_flags ( data [ 6 ] , NULL , 0 ) ) ;
if ( data [ 7 ] )
2020-09-22 16:14:36 +00:00
state - > cur_dive - > dc . duration . seconds = atoi ( data [ 7 ] ) ;
2018-12-29 19:32:55 +00:00
if ( data [ 8 ] )
state - > cur_dive - > dc . surface_pressure . mbar = atoi ( data [ 8 ] ) ;
/*
* TODO : the deviceid hash should be calculated here .
*/
settings_start ( state ) ;
dc_settings_start ( state ) ;
if ( data [ 9 ] )
utf8_string ( data [ 9 ] , & state - > cur_settings . dc . serial_nr ) ;
if ( data [ 10 ] ) {
switch ( atoi ( data [ 10 ] ) ) {
case 2 :
state - > cur_settings . dc . model = strdup ( " Shearwater Petrel/Perdix " ) ;
break ;
case 4 :
state - > cur_settings . dc . model = strdup ( " Shearwater Predator " ) ;
break ;
default :
state - > cur_settings . dc . model = strdup ( " Shearwater import " ) ;
break ;
}
}
state - > cur_settings . dc . deviceid = atoi ( data [ 9 ] ) ;
dc_settings_end ( state ) ;
settings_end ( state ) ;
if ( data [ 10 ] ) {
switch ( atoi ( data [ 10 ] ) ) {
case 2 :
state - > cur_dive - > dc . model = strdup ( " Shearwater Petrel/Perdix " ) ;
break ;
case 4 :
state - > cur_dive - > dc . model = strdup ( " Shearwater Predator " ) ;
break ;
default :
state - > cur_dive - > dc . model = strdup ( " Shearwater import " ) ;
break ;
}
}
if ( data [ 11 ] ) {
snprintf ( get_buffer , sizeof ( get_buffer ) - 1 , get_mode_template , dive_id ) ;
2019-10-26 21:11:44 +00:00
retval = sqlite3_exec ( handle , get_buffer , & shearwater_mode , state , NULL ) ;
2018-12-29 19:32:55 +00:00
if ( retval ! = SQLITE_OK ) {
fprintf ( stderr , " %s " , " Database query shearwater_mode failed. \n " ) ;
return 1 ;
}
}
snprintf ( get_buffer , sizeof ( get_buffer ) - 1 , get_cylinder_template , dive_id ) ;
2019-10-26 21:11:44 +00:00
retval = sqlite3_exec ( handle , get_buffer , & shearwater_cylinders , state , NULL ) ;
2018-12-29 19:32:55 +00:00
if ( retval ! = SQLITE_OK ) {
fprintf ( stderr , " %s " , " Database query shearwater_cylinders failed. \n " ) ;
return 1 ;
}
2020-09-12 18:38:46 +00:00
snprintf ( get_buffer , sizeof ( get_buffer ) - 1 , get_first_gas_template , dive_id ) ;
retval = sqlite3_exec ( handle , get_buffer , & shearwater_changes , state , NULL ) ;
if ( retval ! = SQLITE_OK ) {
fprintf ( stderr , " %s " , " Database query shearwater_changes failed. \n " ) ;
return 1 ;
}
2018-12-29 19:32:55 +00:00
snprintf ( get_buffer , sizeof ( get_buffer ) - 1 , get_changes_template , dive_id ) ;
2019-10-26 21:11:44 +00:00
retval = sqlite3_exec ( handle , get_buffer , & shearwater_changes , state , NULL ) ;
2018-12-29 19:32:55 +00:00
if ( retval ! = SQLITE_OK ) {
fprintf ( stderr , " %s " , " Database query shearwater_changes failed. \n " ) ;
return 1 ;
}
2020-09-19 10:25:47 +00:00
snprintf ( get_buffer , sizeof ( get_buffer ) - 1 , get_profile_template_ai , dive_id , dive_id ) ;
2019-10-26 21:11:44 +00:00
retval = sqlite3_exec ( handle , get_buffer , & shearwater_ai_profile_sample , state , NULL ) ;
2018-12-29 19:32:55 +00:00
if ( retval ! = SQLITE_OK ) {
2020-09-19 10:25:47 +00:00
snprintf ( get_buffer , sizeof ( get_buffer ) - 1 , get_profile_template , dive_id , dive_id ) ;
2019-10-26 21:11:44 +00:00
retval = sqlite3_exec ( handle , get_buffer , & shearwater_profile_sample , state , NULL ) ;
2018-12-29 19:32:55 +00:00
if ( retval ! = SQLITE_OK ) {
fprintf ( stderr , " %s " , " Database query shearwater_profile_sample failed. \n " ) ;
return 1 ;
}
}
dive_end ( state ) ;
return SQLITE_OK ;
}
2017-11-28 19:31:27 +00:00
int parse_shearwater_buffer ( sqlite3 * handle , const char * url , const char * buffer , int size ,
2020-10-17 10:32:22 +00:00
struct dive_table * table , struct trip_table * trips , struct dive_site_table * sites ,
struct device_table * devices )
2017-11-28 19:31:27 +00:00
{
2018-05-22 07:07:42 +00:00
UNUSED ( buffer ) ;
UNUSED ( size ) ;
2017-11-28 19:31:27 +00:00
int retval ;
2018-10-17 16:45:22 +00:00
struct parser_state state ;
init_parser_state ( & state ) ;
state . target_table = table ;
2018-11-26 23:25:15 +00:00
state . trips = trips ;
2019-02-28 21:45:17 +00:00
state . sites = sites ;
2020-10-17 10:32:22 +00:00
state . devices = devices ;
2018-10-17 16:45:22 +00:00
state . sql_handle = handle ;
2017-11-28 19:31:27 +00:00
2018-12-29 20:31:52 +00:00
// So far have not seen any sample rate in Shearwater Desktop
2019-01-03 04:56:48 +00:00
state . sample_rate = 0 ;
2018-12-29 20:31:52 +00:00
2017-11-28 19:31:27 +00:00
char get_dives [ ] = " select l.number,timestamp,location||' / '||site,buddy,notes,imperialUnits,maxDepth,maxTime,startSurfacePressure,computerSerial,computerModel,i.diveId FROM dive_info AS i JOIN dive_logs AS l ON i.diveId=l.diveId " ;
2019-10-26 21:11:44 +00:00
retval = sqlite3_exec ( handle , get_dives , & shearwater_dive , & state , NULL ) ;
2018-10-17 16:45:22 +00:00
free_parser_state ( & state ) ;
2017-11-28 19:31:27 +00:00
if ( retval ! = SQLITE_OK ) {
fprintf ( stderr , " Database query failed '%s'. \n " , url ) ;
return 1 ;
}
return 0 ;
}
2018-12-29 19:32:55 +00:00
int parse_shearwater_cloud_buffer ( sqlite3 * handle , const char * url , const char * buffer , int size ,
2020-10-17 10:32:22 +00:00
struct dive_table * table , struct trip_table * trips , struct dive_site_table * sites ,
struct device_table * devices )
2018-12-29 19:32:55 +00:00
{
UNUSED ( buffer ) ;
UNUSED ( size ) ;
int retval ;
struct parser_state state ;
init_parser_state ( & state ) ;
state . target_table = table ;
2018-11-26 23:25:15 +00:00
state . trips = trips ;
2019-02-28 21:45:17 +00:00
state . sites = sites ;
2020-10-17 10:32:22 +00:00
state . devices = devices ;
2018-12-29 19:32:55 +00:00
state . sql_handle = handle ;
2020-09-19 10:25:47 +00:00
char get_dives [ ] = " select l.number,strftime('%s', DiveDate),location||' / '||site,buddy,notes,imperialUnits,maxDepth,DiveLengthTime,startSurfacePressure,computerSerial,computerModel,d.diveId,l.sampleRateMs / 1000 FROM dive_details AS d JOIN dive_logs AS l ON d.diveId=l.diveId " ;
2018-12-29 19:32:55 +00:00
2019-10-26 21:11:44 +00:00
retval = sqlite3_exec ( handle , get_dives , & shearwater_cloud_dive , & state , NULL ) ;
2018-12-29 19:32:55 +00:00
free_parser_state ( & state ) ;
if ( retval ! = SQLITE_OK ) {
fprintf ( stderr , " Database query failed '%s'. \n " , url ) ;
return 1 ;
}
return 0 ;
}