2017-11-28 19:34:37 +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"
2019-03-04 22:20:29 +00:00
# include "divesite.h"
2018-05-11 15:25:41 +00:00
# include "subsurface-string.h"
2017-11-28 19:34:37 +00:00
# include "parse.h"
# include "divelist.h"
# include "device.h"
# include "membuffer.h"
# include "gettext.h"
2018-10-17 16:45:22 +00:00
static int cobalt_profile_sample ( void * param , int columns , char * * data , char * * column )
2017-11-28 19:34:37 +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:34:37 +00:00
2018-10-17 16:45:22 +00:00
sample_start ( state ) ;
2017-11-28 19:34:37 +00:00
if ( data [ 0 ] )
2018-10-17 16:45:22 +00:00
state - > cur_sample - > time . seconds = atoi ( data [ 0 ] ) ;
2017-11-28 19:34:37 +00:00
if ( data [ 1 ] )
2018-10-17 16:45:22 +00:00
state - > cur_sample - > depth . mm = atoi ( data [ 1 ] ) ;
2017-11-28 19:34:37 +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 ) ) ;
sample_end ( state ) ;
2017-11-28 19:34:37 +00:00
return 0 ;
}
2018-10-17 16:45:22 +00:00
static int cobalt_cylinders ( void * param , int columns , char * * data , char * * column )
2017-11-28 19:34:37 +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:34:37 +00:00
2018-10-17 16:45:22 +00:00
cylinder_start ( state ) ;
2017-11-28 19:34:37 +00:00
if ( data [ 0 ] )
2018-10-17 16:45:22 +00:00
state - > cur_dive - > cylinder [ state - > cur_cylinder_index ] . gasmix . o2 . permille = atoi ( data [ 0 ] ) * 10 ;
2017-11-28 19:34:37 +00:00
if ( data [ 1 ] )
2018-10-17 16:45:22 +00:00
state - > cur_dive - > cylinder [ state - > cur_cylinder_index ] . gasmix . he . permille = atoi ( data [ 1 ] ) * 10 ;
2017-11-28 19:34:37 +00:00
if ( data [ 2 ] )
2018-10-17 16:45:22 +00:00
state - > cur_dive - > cylinder [ state - > cur_cylinder_index ] . start . mbar = psi_to_mbar ( atoi ( data [ 2 ] ) ) ;
2017-11-28 19:34:37 +00:00
if ( data [ 3 ] )
2018-10-17 16:45:22 +00:00
state - > cur_dive - > cylinder [ state - > cur_cylinder_index ] . end . mbar = psi_to_mbar ( atoi ( data [ 3 ] ) ) ;
2017-11-28 19:34:37 +00:00
if ( data [ 4 ] )
2018-10-17 16:45:22 +00:00
state - > cur_dive - > cylinder [ state - > cur_cylinder_index ] . type . size . mliter = atoi ( data [ 4 ] ) * 100 ;
2017-11-28 19:34:37 +00:00
if ( data [ 5 ] )
2018-10-17 16:45:22 +00:00
state - > cur_dive - > cylinder [ state - > cur_cylinder_index ] . gas_used . mliter = atoi ( data [ 5 ] ) * 1000 ;
cylinder_end ( state ) ;
2017-11-28 19:34:37 +00:00
return 0 ;
}
2018-10-17 16:45:22 +00:00
static int cobalt_buddies ( void * param , int columns , char * * data , char * * column )
2017-11-28 19:34:37 +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:34:37 +00:00
if ( data [ 0 ] )
2018-10-17 16:45:22 +00:00
utf8_string ( data [ 0 ] , & state - > cur_dive - > buddy ) ;
2017-11-28 19:34:37 +00:00
return 0 ;
}
/*
* We still need to figure out how to map free text visibility to
* Subsurface star rating .
*/
2018-10-17 16:45:22 +00:00
static int cobalt_visibility ( void * param , int columns , char * * data , char * * column )
2017-11-28 19:34:37 +00:00
{
2018-10-17 16:45:22 +00:00
UNUSED ( param ) ;
2018-05-22 07:07:42 +00:00
UNUSED ( columns ) ;
UNUSED ( column ) ;
UNUSED ( data ) ;
2017-11-28 19:34:37 +00:00
return 0 ;
}
2018-10-17 16:45:22 +00:00
static int cobalt_location ( void * param , int columns , char * * data , char * * column )
2017-11-28 19:34:37 +00:00
{
2018-05-22 07:07:42 +00:00
UNUSED ( columns ) ;
UNUSED ( column ) ;
2018-10-22 13:31:43 +00:00
char * * location = ( char * * ) param ;
* location = data [ 0 ] ? strdup ( data [ 0 ] ) : NULL ;
2017-11-28 19:34:37 +00:00
return 0 ;
}
2018-10-17 16:45:22 +00:00
static int cobalt_dive ( void * param , int columns , char * * data , char * * column )
2017-11-28 19:34:37 +00:00
{
2018-05-22 07:07:42 +00:00
UNUSED ( columns ) ;
UNUSED ( column ) ;
2017-11-28 19:34:37 +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 ;
2017-11-28 19:34:37 +00:00
char * err = NULL ;
2018-10-22 13:31:43 +00:00
char * location , * location_site ;
2017-11-28 19:34:37 +00:00
char get_profile_template [ ] = " select runtime*60,(DepthPressure*10000/SurfacePressure)-10000,p.Temperature from Dive AS d JOIN TrackPoints AS p ON d.Id=p.DiveId where d.Id=%d " ;
char get_cylinder_template [ ] = " select FO2,FHe,StartingPressure,EndingPressure,TankSize,TankPressure,TotalConsumption from GasMixes where DiveID=%d and StartingPressure>0 and EndingPressure > 0 group by FO2,FHe " ;
char get_buddy_template [ ] = " select l.Data from Items AS i, List AS l ON i.Value1=l.Id where i.DiveId=%d and l.Type=4 " ;
char get_visibility_template [ ] = " select l.Data from Items AS i, List AS l ON i.Value1=l.Id where i.DiveId=%d and l.Type=3 " ;
char get_location_template [ ] = " select l.Data from Items AS i, List AS l ON i.Value1=l.Id where i.DiveId=%d and l.Type=0 " ;
char get_site_template [ ] = " select l.Data from Items AS i, List AS l ON i.Value1=l.Id where i.DiveId=%d and l.Type=1 " ;
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:34:37 +00:00
2018-10-17 16:45:22 +00:00
state - > cur_dive - > when = ( time_t ) ( atol ( data [ 1 ] ) ) ;
2017-11-28 19:34:37 +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:34:37 +00:00
/* data[5] should have information on Units used, but I cannot
* parse it at all based on the sample log I have received . The
* temperatures in the samples are all Imperial , so let ' s go by
* that .
*/
2018-10-17 16:45:22 +00:00
state - > metric = 0 ;
2017-11-28 19:34:37 +00:00
/* Cobalt stores the pressures, not the depth */
if ( data [ 6 ] )
2018-10-17 16:45:22 +00:00
state - > cur_dive - > dc . maxdepth . mm = atoi ( data [ 6 ] ) ;
2017-11-28 19:34:37 +00:00
if ( data [ 7 ] )
2018-10-17 16:45:22 +00:00
state - > cur_dive - > dc . duration . seconds = atoi ( data [ 7 ] ) ;
2017-11-28 19:34:37 +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:34:37 +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:34:37 +00:00
if ( data [ 9 ] ) {
2018-10-17 16:45:22 +00:00
utf8_string ( data [ 9 ] , & state - > cur_settings . dc . serial_nr ) ;
state - > cur_settings . dc . deviceid = atoi ( data [ 9 ] ) ;
state - > cur_settings . dc . model = strdup ( " Cobalt import " ) ;
2017-11-28 19:34:37 +00:00
}
2018-10-17 16:45:22 +00:00
dc_settings_end ( state ) ;
settings_end ( state ) ;
2017-11-28 19:34:37 +00:00
if ( data [ 9 ] ) {
2018-10-17 16:45:22 +00:00
state - > cur_dive - > dc . deviceid = atoi ( data [ 9 ] ) ;
state - > cur_dive - > dc . model = strdup ( " Cobalt import " ) ;
2017-11-28 19:34:37 +00:00
}
2018-10-17 16:45:22 +00:00
snprintf ( get_buffer , sizeof ( get_buffer ) - 1 , get_cylinder_template , state - > cur_dive - > number ) ;
retval = sqlite3_exec ( handle , get_buffer , & cobalt_cylinders , state , & err ) ;
2017-11-28 19:34:37 +00:00
if ( retval ! = SQLITE_OK ) {
fprintf ( stderr , " %s " , " Database query cobalt_cylinders failed. \n " ) ;
return 1 ;
}
2018-10-17 16:45:22 +00:00
snprintf ( get_buffer , sizeof ( get_buffer ) - 1 , get_buddy_template , state - > cur_dive - > number ) ;
retval = sqlite3_exec ( handle , get_buffer , & cobalt_buddies , state , & err ) ;
2017-11-28 19:34:37 +00:00
if ( retval ! = SQLITE_OK ) {
fprintf ( stderr , " %s " , " Database query cobalt_buddies failed. \n " ) ;
return 1 ;
}
2018-10-17 16:45:22 +00:00
snprintf ( get_buffer , sizeof ( get_buffer ) - 1 , get_visibility_template , state - > cur_dive - > number ) ;
retval = sqlite3_exec ( handle , get_buffer , & cobalt_visibility , state , & err ) ;
2017-11-28 19:34:37 +00:00
if ( retval ! = SQLITE_OK ) {
fprintf ( stderr , " %s " , " Database query cobalt_visibility failed. \n " ) ;
return 1 ;
}
2018-10-17 16:45:22 +00:00
snprintf ( get_buffer , sizeof ( get_buffer ) - 1 , get_location_template , state - > cur_dive - > number ) ;
2018-10-22 13:31:43 +00:00
retval = sqlite3_exec ( handle , get_buffer , & cobalt_location , & location , & err ) ;
2017-11-28 19:34:37 +00:00
if ( retval ! = SQLITE_OK ) {
fprintf ( stderr , " %s " , " Database query cobalt_location failed. \n " ) ;
return 1 ;
}
2018-10-17 16:45:22 +00:00
snprintf ( get_buffer , sizeof ( get_buffer ) - 1 , get_site_template , state - > cur_dive - > number ) ;
2018-10-22 13:31:43 +00:00
retval = sqlite3_exec ( handle , get_buffer , & cobalt_location , & location_site , & err ) ;
2017-11-28 19:34:37 +00:00
if ( retval ! = SQLITE_OK ) {
fprintf ( stderr , " %s " , " Database query cobalt_location (site) failed. \n " ) ;
return 1 ;
}
2018-10-22 13:31:43 +00:00
if ( location & & location_site ) {
char * tmp = malloc ( strlen ( location ) + strlen ( location_site ) + 4 ) ;
if ( ! tmp ) {
free ( location ) ;
free ( location_site ) ;
return 1 ;
}
sprintf ( tmp , " %s / %s " , location , location_site ) ;
2019-03-05 21:58:47 +00:00
add_dive_to_dive_site ( state - > cur_dive , find_or_create_dive_site_with_name ( tmp , state - > sites ) ) ;
2018-10-22 13:31:43 +00:00
free ( tmp ) ;
}
free ( location ) ;
free ( location_site ) ;
2018-10-17 16:45:22 +00:00
snprintf ( get_buffer , sizeof ( get_buffer ) - 1 , get_profile_template , state - > cur_dive - > number ) ;
retval = sqlite3_exec ( handle , get_buffer , & cobalt_profile_sample , state , & err ) ;
2017-11-28 19:34:37 +00:00
if ( retval ! = SQLITE_OK ) {
fprintf ( stderr , " %s " , " Database query cobalt_profile_sample failed. \n " ) ;
return 1 ;
}
2018-10-17 16:45:22 +00:00
dive_end ( state ) ;
2017-11-28 19:34:37 +00:00
return SQLITE_OK ;
}
int parse_cobalt_buffer ( sqlite3 * handle , const char * url , const char * buffer , int size ,
2019-02-28 21:45:17 +00:00
struct dive_table * table , struct trip_table * trips , struct dive_site_table * sites )
2017-11-28 19:34:37 +00:00
{
2018-05-22 07:07:42 +00:00
UNUSED ( buffer ) ;
UNUSED ( size ) ;
2017-11-28 19:34:37 +00:00
int retval ;
char * err = NULL ;
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 ;
2018-10-17 16:45:22 +00:00
state . sql_handle = handle ;
2017-11-28 19:34:37 +00:00
char get_dives [ ] = " select Id,strftime('%s',DiveStartTime),LocationId,'buddy','notes',Units,(MaxDepthPressure*10000/SurfacePressure)-10000,DiveMinutes,SurfacePressure,SerialNumber,'model' from Dive where IsViewDeleted = 0 " ;
2018-10-17 16:45:22 +00:00
retval = sqlite3_exec ( handle , get_dives , & cobalt_dive , & state , & err ) ;
free_parser_state ( & state ) ;
2017-11-28 19:34:37 +00:00
if ( retval ! = SQLITE_OK ) {
fprintf ( stderr , " Database query failed '%s'. \n " , url ) ;
return 1 ;
}
return 0 ;
}