/****************************************************************************/ /* Copyright 1991 MBARI */ /****************************************************************************/ /* $Header: extract.c,v 3.0 99/05/12 10:11:23 bobh Exp $ */ /* Summary : Program to decode an OASIS binary file */ /* Filename : decode.c */ /* Author : Robert Herlien (rah) */ /* Project : OASIS Mooring */ /* $Revision: 3.0 $ */ /* Created : 12/05/91 */ /****************************************************************************/ /* Modification History: */ /* 05dec91 rah - created */ /* $Log: extract.c,v $ * Revision 3.0 99/05/12 10:11:23 10:11:23 bobh (Bob Herlien) * Added tstring, misc changes * * Revision 2.9 98/08/24 13:45:51 13:45:51 bobh (Bob Herlien) * Archiving sources after M2/M3 & Eqpac deployments of 1998 * * Revision 2.8 98/03/17 11:11:37 11:11:37 bobh (Bob Herlien) * Archiving sources prior to porting to DOS/Windows * * Revision 2.7 97/09/09 09:52:44 09:52:44 bobh (Bob Herlien) * Archiving various changes * * Revision 2.6 96/05/30 15:07:54 15:07:54 bobh (Bob Herlien) * Update for version in use during 1995-6 deployment * * Revision 2.5 94/12/15 10:59:37 10:59:37 hebo (Bob Herlien) * Accumulated minor changes, mainly due to move to tsunami * * Revision 2.4 94/01/21 14:36:13 14:36:13 hebo (Bob Herlien) * Added support for date ranges in cfg file * * Revision 2.2 94/01/17 11:09:41 11:09:41 hebo (Bob Herlien) * Misc changes * * Revision 2.1 92/09/04 13:44:54 13:44:54 hebo (Bob Herlien) * Read CTD pressure from calibration file if no CTD pressure sensor. * * Revision 2.0 92/08/31 15:35:48 15:35:48 hebo (Bob Herlien) * Auguest 1992 Deployment. Changed to allow multiple sensors of same type. * * Revision 1.3 92/06/15 09:07:23 09:07:23 hebo (Bob Herlien) * *** empty log message *** * * Revision 1.2 92/05/12 18:18:39 18:18:39 hebo (Bob Herlien) * Added spectroradiometer decoding (spec.c) * * Revision 1.1 92/03/16 15:42:08 15:42:08 hebo (Bob Herlien) * Ignore leading blanks on "begin" line * * Revision 1.0 92/02/25 10:46:58 10:46:58 hebo (Bob Herlien) * Initial revision */ /****************************************************************************/ #include /* Standard I/O */ #include /* For exit() */ #include /* MBARI type definitions */ #include /* MBARI constants */ #include /* OASIS controller definitions */ #include /* Time */ #include /* for memcpy() */ #include /* for sqrt() */ #include /* for isspace() */ #include /* for strcmp() */ #define BUFSIZE 2048 /* Size of sample buffer */ #define ANALOG_CHANS 8 /* Number of analog channels */ #define PAR_CHAN 0 /* Analog channel number for PARs */ typedef int Boolean; /********************************/ /* External Functions */ /********************************/ Extern FILE *openDataFile( char *name ); Extern Int32 get_begin_line( FILE *fd ); Extern Int32 getRecHdr( Byte *buf, Int len, FILE *fd, FileType ftype ); Extern Int32 readDataFile( Byte *buf, Int len, FILE *fd, FileType ftype ); Extern char *get_can_name( char *dataname ); Extern Status read_cfg( char **cfgname, char *dataname ); Extern Void rcdInit( LogStruct *lp ); Extern MBool readRcd( char *can, LogStruct *lp ); Extern Void writeRcd( char *can, LogStruct *lp ); Extern Void gotRcd( LogStruct *lp, Nat32 lognum, Nat32 rcd ); Extern Status decode_atlas( Byte *atdata, Int atlen, AtlasDecode *adp, AtlasCal *acp ); Extern Status decode_ctd( Byte *ctddata, Int len, CTDDecode *cdp, CTDCal *ccp ); Extern Status decode_no3( Byte *no3data, Int len, No3Decode *no3dp, No3Cal *no3cp ); Extern Status decode_spectro( Byte *spdata, Int splen, SpecDecode *sdp, SpecCal *scp ); Extern Status decode_prr( Byte *spdata, Int len, PrrDecode *sdp, SpecCal *scp ); Extern Status decode_satlantic( Byte *satdata, Int len, SatlanticDecode sdp, SatlanticCal *scp ); Extern Status decode_ac9( Ac9Data *ac9data, Int len, Ac9Decode *ac9 ); Extern Void print_error( char *fmt, ... ); Extern Void print_sensor( Int sensor, char *fmt, ... ); Extern Void close_sensor_files( Void ); Extern Nat16 getIntelword( Byte *p ); Extern Nat32 getIntellong( Byte *p ); Extern Nat16 getHdrWord( Byte *p, FileType ftype ); Extern Nat32 getHdrLong( Byte *p, FileType ftype ); Extern double ctd_salinity(double c, double t, double p); Extern Status print_tstring( Int sensor, Byte *buffer, Int len, TStringCfg *tCfgp ); /********************************/ /* External Data */ /********************************/ Extern char *optarg; /* Option argument from getopt() */ Extern Int optind; /* Option index from getopt() */ Extern Int opterr; /* getopt() error flag */ Extern char can_name[]; /* Name of OASIS can */ Extern char *rcdfile; /* Name of OASIS record number file */ Extern AtlasCal atlas_cal; /* ATLAS calibration */ Extern Analog analog[]; /* Analog calibration */ Extern CTDCal ctd_cal[]; /* Structs to hold CTD calibrations */ Extern No3Cal no3_cal[]; /* Structs to hold NO3 calibrations */ Extern SpecCal spec_cal[]; /* Structs to hold Spect calibrations*/ Extern SatlanticCal satlantic_cal; /* Struct to hold Satlantic cal */ Extern TStringCfg tstringCfg[]; /* Tstring configuration */ Extern GndFltCal gfCal[]; /* Gnd fault board cals */ Extern Int oasisAnalogChan; /* Analog channel number for oasis */ /********************************/ /* Global Data */ /********************************/ Global Int itime; /* Integer year/day as yyddd */ Global double dtime; /* Time in double precision format */ /********************************/ /* Module Local Data */ /********************************/ MLocal Byte buffer[BUFSIZE]; /* Decoded data buffer */ MLocal AtlasDecode atlas; /* Buffer for decoded ATLAS data */ MLocal FileType fileType = FT_UUENCODE; /* Input file type */ MLocal Boolean decode_all = TRUE; /* Decode all sensors */ MLocal Boolean decode_sensor[SENSORS]; /* TRUE to decode particular sensor */ MLocal Boolean nitrate_hdr = TRUE; /* Print "OASIS" header for nitrate */ MLocal Boolean do_rcds = FALSE; /* Update /oasis/raw/oasis.rcd file */ MLocal char *cfgp = NULL; /* Ptr to name of OASIS config file */ MLocal LogStruct logs; /* Which records have been read */ MLocal char *sensor_names[] = { "Empty", "Time", "ATLAS", "OASIS", "PAR", "CTD", "Spectro", "ADCP", "GPS", "Modem", "pCO2", "CTD2", "CTD3", "Spectro10", "Spectro20", "Nitrate", "Nitrate2", "SpecPRR", "Satlantic", "GPS", "NRL", "Oxygen", "Fluorometer", "Transmissometer", "NO3", "NO32", "AC9", "CO2Pump", "H2OPump", "Shutter0", "Shutter1", "SpecPRRVolts", "Metsys", "TString", "GF", "MicroCat", "GPS" }; /********************************/ /* Forward Declarations */ /********************************/ Boolean process_command_line ( Int argc, char **argv ); Void use_msg( char *s ); Void extract_file( char *s ); Void printbytes( Int sensor, Int len ); Void printwords( Int sensor, Int len ); Void print_ascii( Int sensor, Int len, Boolean strip_nl, MBool convert_cr ); Void print_analog( Int sensor, Int chan, Int nchans ); Void print_nitrate( Int sensor, Int len ); Status print_nitrate_decoded( Int sensor, Int len, No3Cal *no3cp ); Void print_gps( Int len ); Void print_gps_type2( Int len ); Void print_gps_type3( Int len ); Status print_ctd( Int sensor, Int len, CTDCal *ccp ); Status print_spec( Int sensor, Int len, SpecCal *scp ); Status print_spec_prr( Int sensor, Int len, SpecCal *scp ); Status print_satlantic( Int sensor, Int len, SatlanticCal *scp ); Status print_ac9( Int sensor, Int len ); Void print_shutter( Int sensor, Int len ); Void print_gndflt( Int sensor, Int len, GndFltCal *gfp ); Void print_metsys( Int sensor, Int len ); Void sensor_error( Int sensor, Status err ); Void oasis_error( Int err, time_t errTm ); /************************************************************************/ /* Function : main */ /* Purpose : Main routine */ /* Inputs : argc, argv */ /* Outputs : none */ /************************************************************************/ Void main( Int argc, char **argv ) { Int i; char *filename, *cp; if ( !process_command_line(argc, argv) ) { use_msg(argv[0]); exit( 1 ); } for ( i = optind; i < argc; i++ ) { filename = argv[i]; cp = cfgp; get_can_name( filename ); rcdInit( &logs ); if ( read_cfg(&cp, filename) != OK ) fprintf(stderr, "Can't read configuration file \"%s\"\n", cp); else if ( do_rcds ) { readRcd( can_name, &logs ); extract_file( filename ); writeRcd( can_name, &logs ); } else extract_file( filename ); } exit( 0 ); } /* main() */ /************************************************************************/ /* Function : extract_file */ /* Purpose : Extract data from one data file */ /* Inputs : File name */ /* Outputs : none */ /************************************************************************/ Void extract_file( char *filename ) { Int cc, len, len_got; Int16 err; FILE *fd; struct tm *tp; Boolean did_err_msg; Status rtn; Int32 lognum; LogRecHdr hdr; lognum = 0; did_err_msg = FALSE; if ( (fd = openDataFile(filename)) == (FILE *)NULL ) return; if ( (fileType == FT_UUENCODE) && ((lognum = get_begin_line(fd)) < 0) ) { printf("No begin line in %s\n", filename); fclose( fd ); return; } while ( (cc = getRecHdr(buffer, sizeof(buffer), fd, fileType)) != EOF ) { if ( cc == UUEND ) { if( (lognum = get_begin_line(fd)) < 0 ) break; else continue; } if ( cc == 0 ) continue; did_err_msg = FALSE; hdr.log_type = buffer[0]; hdr.log_nmbr = getHdrWord(&buffer[1], fileType); hdr.log_len = getHdrWord(&buffer[3], fileType); hdr.log_time = getHdrLong(&buffer[5], fileType); tp = gmtime( (time_t *)&hdr.log_time ); itime = (1000 * tp->tm_year) + tp->tm_yday + 1; dtime = tp->tm_yday + 1.0 + (double)((3600 * tp->tm_hour) + (60 * tp->tm_min) + tp->tm_sec) / 86400.0; len_got = cc - 9; /* compute amount of log data gotten*/ if ( len_got > 0 ) memmove( buffer, buffer + 9, sizeof(buffer) - 9 ); else if ( len_got < 0 ) /* Move log data to start of buffer*/ { printf("Incomplete record header\n"); continue; } if ( (len = hdr.log_len) > (Int32)sizeof(buffer) ) { len = sizeof(buffer); print_error("Record too long in %s. Truncating.\n", filename); continue; } if ( len_got < len ) { len_got += readDataFile(buffer+len_got, len-len_got, fd, fileType); if ( len_got != len) { if ( !did_err_msg ) printf("Bad record in %s block %d record %d\n", filename, lognum, hdr.log_nmbr); did_err_msg = TRUE; continue; } did_err_msg = FALSE; } if ( do_rcds ) gotRcd( &logs, lognum, hdr.log_nmbr ); if ( !decode_all && !((hdr.log_type < SENSORS) && decode_sensor[hdr.log_type]) ) continue; switch( hdr.log_type ) { case LOG_EMPTY: print_error("Empty record in file %s\n", filename); break; case OASIS_STAT: break; case ATLAS: if ( (rtn = decode_atlas(buffer, len, &atlas, &atlas_cal)) != OK ) { sensor_error( ATLAS, rtn ); break; } print_sensor( ATLAS, "%9.5f %9.5f %6.3f %6.3f ", dtime, atlas.atd_time, atlas.atd_air, atlas.atd_sst ); for ( cc = 0; cc < TEMPS; cc++ ) print_sensor( ATLAS, "%6.3f ", atlas.atd_temp[cc] ); print_sensor( ATLAS, "%6.2f %6.2f %5.2f ", atlas.atd_press[0], atlas.atd_press[1], atlas.atd_rh); print_sensor( ATLAS, "%6.3f %5.1f %6.3f %6.3f ", atlas.atd_windspd, atlas.atd_winddir, atlas.atd_windu, atlas.atd_windv ); print_sensor( ATLAS, "%3.0f %3.0f %3.0f %5.2f\n", atlas.atd_compass, atlas.atd_vane, atlas.atd_rawdir, atlas.atd_rawspeed ); break; case OASIS_CAN: print_analog(OASIS_CAN, oasisAnalogChan, len/2); break; case PAR: print_analog(PAR, PAR_CHAN, len/2); break; case CTD: print_ctd( CTD, len, &ctd_cal[CTD_CAL] ); break; case CTD2: print_ctd( CTD2, len, &ctd_cal[CTD2_CAL] ); break; case CTD3: print_ctd( CTD3, len, &ctd_cal[CTD3_CAL] ); break; case SPECTRO: print_spec( SPECTRO, len, &spec_cal[SPECTRO_CAL] ); break; case SPECTRO2: print_spec( SPECTRO2, len, &spec_cal[SPECTRO2_CAL] ); break; case SPECTRO3: print_spec( SPECTRO3, len, &spec_cal[SPECTRO3_CAL] ); break; case SPEC_PRR: print_spec_prr( SPEC_PRR, len, &spec_cal[SPECPRR_CAL] ); print_spec_prr( SPEC_PRR_VOLTS, len, (SpecCal *)NULL ); break; case SATLANTIC: print_satlantic( SATLANTIC, len, &satlantic_cal ); break; case ADCP: printbytes( ADCP, len ); break; case GPS: print_gps( len ); break; case GPS_TYPE2: print_gps_type2( len ); break; case GPS_TYPE3: print_gps_type3( len ); break; case PCO2: print_ascii(PCO2, len, TRUE, FALSE); break; case NO3: print_nitrate(NO3, len); print_nitrate_decoded(NO3_DECODED, len, &no3_cal[NO3_CAL]); break; case NO32: print_nitrate(NO32, len); print_nitrate_decoded(NO3_DECODED2, len, &no3_cal[NO3_CAL2]); break; case NRL: print_ascii(NRL, len, FALSE, FALSE); break; case O2: print_ascii(O2, len, TRUE, FALSE); break; case FLUOR: print_analog( FLUOR, FLUOR_CHAN, len/2 ); break; case TRANSMISS: print_analog( TRANSMISS, TRANSMISS_CHAN, len/2 ); break; case AC9: print_ac9( AC9, len ); break; case SHUTTER0: case SHUTTER1: print_shutter( hdr.log_type, len ); break; case METSYS: print_metsys(METSYS, len); break; case TSTRING: print_tstring( TSTRING, buffer, len, tstringCfg ); break; case GNDFAULT: print_gndflt( GNDFAULT, len, gfCal ); break; case MICROCAT: print_ascii(MICROCAT, len, FALSE, TRUE); break; case LOG_ERROR: cc = getIntelword(buffer); err = (Int16)getIntelword(buffer + sizeof(Nat16)); if ( cc & 0x8000 ) oasis_error( cc & 0x7fff, hdr.log_time ); else sensor_error( cc, err ); break; case LOG_COMMENT: print_error("Comment Record: %s\n", buffer); break; case CO2_PUMP: case H2O_PUMP: case LOG_BIN: break; case LOG_DISK_ERROR: print_error( "Disk Error, Rtn code %#x\n", (Nat32)getIntelword(buffer) ); break; default: print_error("Unknown record type in %s\n", filename); } } fclose( fd ); } /* extract_file() */ /************************************************************************/ /* Function : use_msg */ /* Purpose : Print Usage Message */ /* Inputs : Name of program */ /* Outputs : None */ /************************************************************************/ Void use_msg( char *s ) { fprintf( stderr, "Usage: %s [-b] [-c cfg_file] [-f rcd_file] [-h] [-i instrument] [-n] [-r]\n", s ); fprintf( stderr, "c configuration file name\n" ); fprintf( stderr, "f record number file name\n" ); fprintf( stderr, "h interprets data as hex file (default is uuencode)\n" ); fprintf( stderr, "b interprets data as binary file (default is uuencode)\n" ); fprintf( stderr, "i extract only named instrument(s)\n" ); fprintf( stderr, "n do not add header to nitrate file\n" ); fprintf( stderr, "r use record numbers with default file %s\n", rcdfile ); } /* use_msg() */ /************************************************************************/ /* Function : process_command_line */ /* Purpose : Read the arguments from the command line */ /* Inputs : argc, argv from main() routine */ /* Outputs : TRUE if arguments OK, else FALSE */ /************************************************************************/ Boolean process_command_line ( Int argc, char **argv ) { Int i, baud; for ( i = 0; i < SENSORS; i++ ) decode_sensor[i] = FALSE; while ( (i = getopt(argc, argv, "bc:f:hi:nr")) != EOF ) switch( i ) { case 'b': fileType = FT_BIN; break; case 'c': cfgp = optarg; break; case 'f': do_rcds = TRUE; rcdfile = optarg; break; case 'h': fileType = FT_HEX; break; case 'i': for ( i = 0; i < SENSORS; i++ ) if ( strcasecmp(optarg, sensor_names[i]) == 0 ) { decode_all = FALSE; decode_sensor[i] = TRUE; } break; case 'n': nitrate_hdr = FALSE; break; case 'r': do_rcds = TRUE; break; default: return( FALSE ); } return( TRUE ); } /* process_command_line() */ /************************************************************************/ /* Function : printbytes */ /* Purpose : Print data stream as a stream of bytes */ /* Inputs : Sensor, length */ /* Outputs : None */ /************************************************************************/ Void printbytes( Int sensor, Int len ) { Int i; print_sensor( sensor, "%9.5f ", dtime ); for ( i = 0; i < len; i++ ) print_sensor( sensor, "%02x", buffer[i] ); print_sensor( sensor,"\n"); } /* printbytes() */ /************************************************************************/ /* Function : printwords */ /* Purpose : Print data stream as a stream of words */ /* Inputs : Sensor, length */ /* Outputs : None */ /************************************************************************/ Void printwords( Int sensor, Int len ) { Int i; print_sensor( sensor, "%9.5f ", dtime ); for ( i = 0; i < len; i += 2 ) print_sensor( sensor, "%04x ", getIntelword(buffer + i) ); print_sensor( sensor,"\n"); } /* printwords() */ /************************************************************************/ /* Function : print_ascii */ /* Purpose : Print data stream as ascii stream */ /* Inputs : Sensor, Length, Boolean to strip CR & LF */ /* Outputs : None */ /************************************************************************/ Void print_ascii( Int sensor, Int len, Boolean strip_nl, MBool convert_cr ) { char *p; buffer[len] = '\0'; if ( strip_nl ) { while ( (p = strchr((char *)buffer, '\r')) != NULL ) *p = ' '; while ( (p = strchr((char *)buffer, '\n')) != NULL ) *p = ' '; } if ( convert_cr ) { while ( (p = strchr((char *)buffer, '\r')) != NULL ) *p = '\n'; } print_sensor(sensor, "%9.5f %s\n", dtime, buffer); } /* print_ascii() */ /************************************************************************/ /* Function : print_analog */ /* Purpose : Print data stream as analog channel data */ /* Inputs : Sensor, first channel number, number of channels */ /* Outputs : None */ /************************************************************************/ Void print_analog( Int sensor, Int chan, Int nchans ) { Int i; Reg Analog *ap; print_sensor( sensor, "%9.5f ", dtime ); for ( i = 0; i < nchans; i++ ) { ap = &analog[chan + i]; print_sensor( sensor, "%7.2f ", (((ap->a * (double)getIntelword(&buffer[2*i])) + ap->b) * ap->c) + ap->d ); } print_sensor( sensor, "\n"); } /* print_analog() */ /************************************************************************/ /* Function : print_nitrate */ /* Purpose : Print nitrate data */ /* Inputs : Sensor, Length */ /* Outputs : None */ /************************************************************************/ Void print_nitrate( Int sensor, Int len ) { char *p; buffer[len] = '\0'; while ( (p = strchr((char *)buffer, '\r')) != NULL ) *p = ' '; if ( nitrate_hdr ) print_sensor(sensor, "OASIS %9.5f\n%s", dtime, buffer); else print_sensor(sensor, "%s", buffer); } /* print_nitrate() */ /************************************************************************/ /* Function : print_nitrate_decoded */ /* Purpose : Decode and print decoded nitrate data */ /* Inputs : Sensor, Length, calibration struct */ /* Outputs : OK or Error type */ /************************************************************************/ Status print_nitrate_decoded( Int sensor, Int len, No3Cal *no3cp ) { Reg Byte *p, *q; /* Scratch ptrs */ No3Decode no3; /* Struct to hold decoded NO3 data */ Status rtn; /* Return code */ buffer[len] = '\0'; for ( p = buffer; p - buffer < len; p = q ) { /* Loop to decode one line at a time*/ while ( (p - buffer < len) && ((*p == '\r') || (*p == '\n')) ) p++; if ( (q = (Byte *)strchr((char *)p, '\r')) == NULL ) q = (Byte *)strchr((char *)p, '\n'); if ( (q != NULL) && (q - buffer < len) ) *q++ = '\0'; else q = p + strlen((char *)p) + 1; if ( (rtn = decode_no3(p, len, &no3, no3cp)) == OK ) { if ( no3cp->nc_format == NO3_DRIFT1 ) print_sensor(sensor, "%-.14s %6.4f %6.3f %6.4f %6.4f\n", no3.no3_time, no3.no3_conc, no3.no3_temp, no3.no3_salinity, no3.no3_conductivity); else print_sensor(sensor, "%-.14s %6.4f %6.3f\n", no3.no3_time, no3.no3_conc, no3.no3_temp); } } } /* print_nitrate_decoded() */ /************************************************************************/ /* Function : print_gps */ /* Purpose : Print buffer as GPS data */ /* Inputs : Length of buffer */ /* Outputs : None */ /************************************************************************/ Void print_gps( Int len ) { Int32 lat, lon; Nat32 var; Nat16 samples, status; if ( len != 16 ) sensor_error( GPS, SIZE_ERR ); lat = getIntellong(buffer); lon = getIntellong(&buffer[4]); var = getIntellong(&buffer[8]); samples = getIntelword(&buffer[12]); status = getIntelword(&buffer[14]); print_sensor(GPS, "%9.5f %10.5f %10.5f %5.2f %3d %04x\n", dtime, (double)lat/60000.0, (double)lon/60000.0, sqrt((double)var), samples, status ); } /* print_gps() */ /************************************************************************/ /* Function : print_gps_type2 */ /* Purpose : Print buffer as GPS data */ /* Inputs : Length of buffer */ /* Outputs : None */ /************************************************************************/ Void print_gps_type2( Int len ) { Int32 lat, lon; Nat32 var; Nat16 samples, totTime, status; if ( len != 18 ) { sensor_error( GPS, SIZE_ERR ); return; } lat = getIntellong(buffer); lon = getIntellong(&buffer[4]); var = getIntellong(&buffer[8]); samples = getIntelword(&buffer[12]); totTime = getIntelword(&buffer[14]); status = getIntelword(&buffer[16]); print_sensor(GPS, "%9.5f %10.5f %10.5f %5.2f %3d %3d %04x\n", dtime, (double)lat/10000000., (double)lon/10000000., sqrt((double)var), samples, totTime, status ); } /* print_gps_type2() */ /************************************************************************/ /* Function : print_gps_type3 */ /* Purpose : Print buffer as GPS data */ /* Inputs : Length of buffer */ /* Outputs : None */ /************************************************************************/ Void print_gps_type3( Int len ) { Int32 lat, lon; Nat32 var; Nat16 fmt, samples, totTime, diffSamples, hdop, status; if ( (fmt = getIntelword(buffer)) != 1 ) sensor_error( GPS, FMT_ERR ); if ( len != 24 ) sensor_error( GPS, SIZE_ERR ); samples = getIntelword(&buffer[2]); lat = getIntellong(&buffer[4]); lon = getIntellong(&buffer[8]); var = getIntellong(&buffer[12]); totTime = getIntelword(&buffer[16]); diffSamples = getIntelword(&buffer[18]); hdop = getIntelword(&buffer[20]); status = getIntelword(&buffer[22]); print_sensor(GPS, "%9.5f %10.5f %10.5f %5.2f %3d %3d %3d %4.1f %d %02x\n", dtime, (double)lat/600000.0, (double)lon/600000.0, sqrt((double)var), samples, totTime, diffSamples, 0.1*hdop, (status>>8) & 0xff, status & 0xff); } /* print_gps_type3() */ /************************************************************************/ /* Function : print_ctd */ /* Purpose : Print buffer as CTD data */ /* Inputs : Sensor, Length of buffer, CTD calibration struct */ /* Outputs : OK or Error type /************************************************************************/ Status print_ctd( Int sensor, Int len, CTDCal *ccp ) { CTDDecode ctd; /* Struct to hold decoded CTD data */ Status rtn; /* Return code */ if ( (rtn = decode_ctd(buffer, len, &ctd, ccp)) != OK ) { sensor_error( sensor, rtn ); return( rtn ); } print_sensor(sensor, "%9.5f %d %6.3f %6.3f %6.3f %6.4f %6.4f %6.4f\n", dtime, ctd.ctd_sample, ctd.ctd_press, ctd.ctd_temp, ctd.ctd_cond, ctd.ctd_sal, ctd.ctd_trans, ctd.ctd_fluor); return( OK ); } /* print_ctd() */ /************************************************************************/ /* Function : print_spec */ /* Purpose : Print buffer as Spectroradiometer data */ /* Inputs : Sensor, Length of buffer, Spectro calibration struct */ /* Outputs : OK or Error type */ /************************************************************************/ Status print_spec( Int sensor, Int len, SpecCal *scp ) { Int i, j; /* Scratch */ Status rtn; /* Return code */ SpecDecode spec; /* Struct to hold decoded Spect data*/ if ( (rtn = decode_spectro(buffer, len, &spec, scp)) != OK ) { sensor_error( sensor, rtn ); return( rtn ); } print_sensor(sensor, "%9.5f %9.5f ", dtime, spec.spc_day + (double)(spec.spc_sec)/86400.0); for ( i = 0; i < SPEC_BANKS; i++ ) for ( j = 0; j < scp->spc_nchans[i]; j++ ) { if ( scp->spc_cal[i][j].type > 0 ) print_sensor(sensor, "%9.6f %9.6f %9.6f %9.6f ", spec.spc_chan[i][j].spc_mean, spec.spc_chan[i][j].spc_std, spec.spc_chan[i][j].spc_min, spec.spc_chan[i][j].spc_max); } print_sensor(sensor, "\n"); return( OK ); } /* print_spec() */ /************************************************************************/ /* Function : print_spec_prr */ /* Purpose : Print buffer as PRR-600 Spectroradiometer data */ /* Inputs : Sensor, Length of buffer, Spectro calibration struct */ /* If scp is NULL, prints raw voltages */ /* Outputs : OK or Error type */ /************************************************************************/ Status print_spec_prr( Int sensor, Int len, SpecCal *scp ) { Int bank, chan; /* Bank, channel numbers */ Status rtn; /* Return code */ PrrDecode specprr; /* Decoded PRR Spectro data */ if ( (rtn = decode_prr(buffer, len, &specprr, scp)) != OK ) { sensor_error( sensor, rtn ); return( rtn ); } print_sensor(sensor, "%9.5f ", dtime); for ( bank = 0; bank < specprr.prr_nbanks; bank++ ) for ( chan = 0; (chan < specprr.prr_bank[bank].prr_nchans); chan++ ) if ( (scp == (SpecCal *)NULL) || (scp->spc_cal[bank][chan].type > 0) ) print_sensor(sensor, "%9.6f ", specprr.prr_bank[bank].prr_chan[chan]); print_sensor(sensor, "\n"); return( OK ); } /* print_spec_prr() */ /************************************************************************/ /* Function : print_satlantic */ /* Purpose : Print buffer as Satlantic spectroradiometer data */ /* Inputs : Sensor, Length of buffer, Satlantic calibration struct */ /* Outputs : OK or Error type */ /************************************************************************/ Status print_satlantic( Int sensor, Int len, SatlanticCal *scp ) { Int chan; /* Channel number */ Status rtn; /* Return code */ SatlanticDecode satlantic; /* Decoded Satlantic data */ if ( (rtn = decode_satlantic(buffer, len, satlantic, scp)) != OK ) { sensor_error( sensor, rtn ); return( rtn ); } print_sensor(sensor, "%9.5f", dtime); for ( chan = 0; chan < scp->sat_chans; chan++ ) print_sensor(sensor, " %9.6f", satlantic[chan]); print_sensor(sensor, "\n"); return( OK ); } /* print_satlantic() */ /************************************************************************/ /* Function : print_ac9 */ /* Purpose : Print buffer as AC-9 data */ /* Inputs : Length of buffer */ /* Outputs : OK or Error type */ /************************************************************************/ Status print_ac9( Int sensor, Int len ) { Status rtn; Int chan; Ac9Decode ac9; if ( (rtn = decode_ac9((Ac9Data *)buffer, len, &ac9)) != OK ) { sensor_error( sensor, rtn ); return( rtn ); } print_sensor(sensor, "%9.5f %2d %2d", dtime, AC9_CHANS, ac9.ac9_samples); for ( chan = 0; chan < AC9_CHANS; chan++ ) print_sensor(sensor, " %9.5f", ac9.ac9_value[chan]); print_sensor( sensor, " %9.5f\n", ac9.ac9_temp ); return( OK ); } /* print_ac9() */ /************************************************************************/ /* Function : print_shutter */ /* Purpose : Print shutter log record */ /* Inputs : Sensor, length */ /* Outputs : None */ /************************************************************************/ Void print_shutter( Int sensor, Int len ) { Word status; if ( len < (Int)(2 * sizeof(Word)) ) { sensor_error( sensor, SIZE_ERR ); return; } print_sensor( sensor, "%9.5f ", dtime ); status = getIntelword( buffer + sizeof(Word) ); print_sensor( sensor, "%4d %04x %2d %2d %2d ", getIntelword(buffer), status, ((status >> 12) & 7), (status & 0xff), ((status >> 8) & 0x0f) ); if ( status & 0x8000 ) print_sensor( sensor,"open\n"); else print_sensor( sensor,"close\n"); } /* print_shutter() */ /************************************************************************/ /* Function : print_gndflt */ /* Purpose : Print Ground Fault data */ /* Inputs : Sensor, length, calibr struct */ /* Outputs : None */ /************************************************************************/ Void print_gndflt( Int sensor, Int len, GndFltCal *gfp ) { Reg int i; Reg GndFltCal *gfPtr; Reg Nat16 raw; double value; print_sensor( sensor, "%9.5f ", dtime ); for ( i = 0, gfPtr = gfp; i < MAX_GF_CALS; i++, gfPtr++ ) if ( gfPtr->cal_valid && (len >= (Int)(gfPtr->raw_offset + sizeof(Nat16))) ) { raw = getMotword( buffer + gfPtr->raw_offset ); value = (double)(raw - gfPtr->cal_offset) / gfPtr->cal_divisor; print_sensor( sensor, "%6.3f ", value ); } print_sensor( sensor, "\n" ); } /* print_gndflt() */ /************************************************************************/ /* Function : print_metsys */ /* Purpose : Print data stream as ascii stream */ /* Inputs : Sensor, Length, Boolean to strip CR & LF */ /* Outputs : None */ /************************************************************************/ Void print_metsys( Int sensor, Int len) { char *p; char *metsys_string[22]; int i = 0; int hrmin; double variation = 15.1; Metsys metsys; buffer[len] = '\0'; metsys_string[i] = strtok(buffer, "+- "); while ((p = strtok(NULL, "+- ")) != NULL) { i++; metsys_string[i] = p; switch(i) { case 1: metsys.arr_type = atoi(metsys_string[i]); break; case 3: metsys.day = atoi(metsys_string[i]); break; case 5: hrmin = atoi(metsys_string[i]); metsys.hr = hrmin / 100; metsys.min = hrmin % 100; break; case 7: metsys.batt_volt = atof(metsys_string[i]); break; case 9: metsys.air = atof(metsys_string[i]); break; case 11: metsys.rh = atof(metsys_string[i]); break; case 13: metsys.baro_press = atof(metsys_string[i]); break; case 15: metsys.windspd = atof(metsys_string[i]); break; case 17: metsys.winddir = atof(metsys_string[i]); break; case 19: metsys.buoy_heading = atof(metsys_string[i]); break; case 21: metsys.rel_winddir = atof(metsys_string[i]); break; } } if ( (metsys.arr_type == 303) || (metsys.arr_type == 304) ) { metsys.winddir = metsys.winddir + variation; while ( metsys.winddir >= 360.0 ) metsys.winddir -= 360.0; metsys.baro_press += 800; } metsys.windu = -metsys.windspd*sin(metsys.winddir*PI/180.0); metsys.windv = -metsys.windspd*cos(metsys.winddir*PI/180.0); print_sensor(sensor, "%9.5f %d %d %d %d %6.2f %6.2f %5.1f %6.1f %7.3f %6.2f %6.2f %6.2f %6.2f %6.2f\n", dtime, metsys.arr_type, metsys.day, metsys.hr, metsys.min, metsys.batt_volt, metsys.air, metsys.rh, metsys.baro_press, metsys.windspd, metsys.winddir, metsys.windu, metsys.windv, metsys.buoy_heading, metsys.rel_winddir); } /* print_metsys() */ #if 0 /* Old way of doing it. New way is in tstring.c */ /************************************************************************/ /* Function : print_tstring */ /* Purpose : Print data from Inductive Modem Temperature String */ /* Inputs : Sensor, Length */ /* Outputs : None */ /************************************************************************/ Void print_tstring( Int sensor, Int len ) { char *datap, *linep; Reg Int32 cnt; Int32 dummy1; Flt32 dummy2; buffer[len] = '\0'; print_sensor( sensor, "%9.5f\n", dtime ); for ( datap = buffer, cnt = 0; *datap && (cnt < len); ) { linep = datap; for ( ; *datap && (cnt < len); datap++, cnt++ ) if ( (*datap == '\r') || (*datap == '\n') ) { *datap++ = '\0'; cnt++; break; } if ( sscanf(linep, " %d, %g", &dummy1, &dummy2) == 2 ) print_sensor(sensor, "%s\n", linep); } } /* print_tstring() */ #endif /************************************************************************/ /* Function : sensor_error */ /* Purpose : Print sensor error */ /* Inputs : Instrument type, Error type */ /* Outputs : None */ /************************************************************************/ Void sensor_error( Int sensor, Status err ) { Int n; if ( sensor >= SENSORS ) { print_error("Unknown Error type\n"); return; } n = (Int)((1440.0 * fmod(dtime, 1.0)) + 0.5); print_error("%2d:%02d %s Error", n / 60, n % 60, sensor_names[sensor]); switch( err ) { case ERROR: print_error(" reported by OASIS.\n"); break; case TMOUT_ERR: print_error(". OASIS reports timeout\n"); break; case MALLOC_ERR: print_error(". OASIS had no buffer space\n"); break; case NO_DATA: print_error(". OASIS reports no data\n"); break; case BAD_DATA: print_error(". OASIS reports bad data\n"); break; case CKSUM_ERR: print_error(". OASIS reports checksum error.\n"); break; case SYNC_ERR: print_error(". OASIS reports sync error.\n"); break; case NOT_AVAIL_ERR: print_error(". OASIS device reports not available\n"); break; case SIZE_ERR: print_error(". Wrong size.\n"); break; case CHKSUM_ERR: print_error(". Checksum error.\n"); break; case FMT_ERR: print_error(". Bad data format.\n"); break; case GPS_OOPS: if ( sensor == GPS_TYPE2 ) { print_error(". No first fix\n"); break; } default: print_error(". Bad data error type %#x\n", err); break; } } /* sensor_error() */ /************************************************************************/ /* Function : oasis_error */ /* Purpose : Print oasis error */ /* Inputs : Error word */ /* Outputs : None */ /************************************************************************/ Void oasis_error( Int err, time_t errTm ) { struct tm *tp; tp = gmtime( &errTm ); print_error("%2d:%02d OASIS Error ", tp->tm_hour, tp->tm_min); if ( err & RAM_ERR ) print_error("RAM_init "); if ( err & LOG_ERR ) print_error("LOG_memory_bad "); if ( err & CLOCK_ERR ) print_error("Clock_failure "); if ( err & INT_ERR ) print_error("Spurious_interrupt "); if ( err & RESTART_ERR ) print_error("Restarted "); if ( err & COMM_ERR ) print_error("24hr_silence"); if ( err & DISK_ERR ) print_error("Disk Write Error "); if ( err & ARGOS_ERR ) print_error("ARGOS Error "); print_error("\n"); } /* oasis_error() */