/* Collect GPS data from a file, COM port or Serial port. Parse NEMA-183 format GPS sentences, convert from degrees minutes to decimal degrees, and write the result to a text file. The resulting file can then be used in ArcView GIS. Compiles on: Windows, DOS, Linux and other POSIX Compatible Unix systems. Author: Bryce Nesbitt Website: http://www.obviously.com */ #include #include #define unless(x) if(!(x)) #define LINEBUF_SIZE 1024 #define FILEBUF_SIZE 80 #define VERSION "0.5" #undef Linux #ifdef Linux char infilename[] = "nema.txt"; char outfilename[] = "/tmp/gpsfix.txt"; #else char infilename[] = "COM1"; char outfilename[] = "c:\\gpsfix.txt"; #endif char linebuf[LINEBUF_SIZE]; char filebuf[FILEBUF_SIZE]; struct gpsfix { float time; float lat; float lon; float lat_deg; float lon_deg; int quality; }; int parse_nema( char * , struct gpsfix * ); int main(int argc, char *argv[]) { FILE *fp_in; FILE *fp_out; struct gpsfix fix; char *portname = infilename; printf("GPS Fixit for ArcView 3.x %s\n", VERSION); // First argument overrides default input source if( argc == 2 ) { portname = argv[1]; } unless( fp_in = fopen(portname, "r") ) { printf("Unable to open %s for reading\n", portname); return(5); } printf("Reading data from %s, writing to %s\n", portname, outfilename); // Set line buffering. But with Windows _IOLBF is ignored, how nice. // So instead we set a small buffer that gets full all the time. setvbuf( fp_in, filebuf, _IOLBF, FILEBUF_SIZE ); while( fgets( linebuf, LINEBUF_SIZE, fp_in ) ) { if( parse_nema( linebuf, &fix ) ) { // write gps data to temporary file... // snprintf(linebuf,LINEBUF_SIZE, "%f,%f\n", fix.lat/100, fix.lon/100); sprintf(linebuf,"%f,%f,%06.0f\n", fix.lat_deg, fix.lon_deg, fix.time); if( fp_out = fopen(outfilename, "w") ) { fputs( linebuf, fp_out ); fclose( fp_out ); printf(" %s", linebuf); } } } fclose( fp_in ); printf("Exiting...\n"); unlink( outfilename ); return(0); } int parse_nema( char * nema_gps_string, struct gpsfix * fixit ) { char latdir,londir; int latDegrees; float latMinutes; int lonDegrees; float lonMinutes; // $GPGAA,hhmmss.ss,ddmm.mmmm,n,dddmm.mmmm,e,q,ss,y.y,a.a,z,g.g,z,t.t,iii*CC if( 0 == strncmp( "$GPGGA", nema_gps_string, 6 ) ) { printf("%s", nema_gps_string); sscanf( nema_gps_string, "$GPGGA,%f,%f,%c,%f,%c,%d", &fixit->time,&fixit->lat,&latdir,&fixit->lon,&londir,&fixit->quality); if(latdir == 'S') fixit->lat = 0-(fixit->lat); if(londir == 'W') fixit->lon = 0-(fixit->lon); latDegrees = (int)(fixit->lat/100); latMinutes = (float)(fixit->lat - latDegrees*100); fixit->lat_deg = latDegrees + (latMinutes/60); // Concert to decimal degrees lonDegrees = (int)(fixit->lon/100); lonMinutes = (float)(fixit->lon - lonDegrees*100); fixit->lon_deg = lonDegrees + (lonMinutes/60); // Convert to decimal degrees printf(" %+02d Degrees %+2.6f Minutes Latitude\n", latDegrees, latMinutes); printf(" %+02d Degrees %+2.6f Minutes Longitude\n", lonDegrees, lonMinutes); return(1); } return(0); }