--- bluez-utils-2.23/tools/hcitool.c 2005-10-29 19:04:29.000000000 -0400 +++ hcitool.c 2005-12-26 17:19:52.000000000 -0500 @@ -1,4 +1,26 @@ /* + Merged code from Bryce Nesbitt with hcitool... + Added code to loop the hcitool scan via --loop option. + kf_lists[at]digitalmunition[dot]com + http://www.digitalmunition.com + + animosity:/home/kfinisterre# hcitool scan + Scanning ... + 00:60:57:DC:32:04 Nokia 3660 + 00:0C:A5:00:79:60 NAVMAN GPS ONE + animosity:/home/kfinisterre# rfcomm connect 0 00:0C:A5:00:79:60 1 + Connected /dev/rfcomm0 to 00:0C:A5:00:79:60 on channel 1 + Press CTRL-C for hangup + + kfinisterre@animosity:~/bluez-utils-2.23/tools$ ./hcitool scan + Scanning ... + 00:04:3E:65:A1:C8 Pocket_PC lat: 39.xxxxxx lon: -83.xxxxxx sats: 6 + + kfinisterre@animosity:~/bluez-utils-2.23/tools$ tail -n1 hcitool-gps.log + Pocket_PC, 00:04:3E:65:A1:C8, 39.xxxxxx,-83.xxxxxx, time: 214035, sats: 6 + +*/ +/* * * BlueZ - Bluetooth protocol stack for Linux * @@ -48,6 +70,7 @@ #define for_each_opt(opt, long, short) while ((opt=getopt_long(argc, argv, short ? short:"+", long, NULL)) != -1) +int gps(char *extra, char *extra2); static void usage(void); static int dev_info(int s, int dev_id, long arg) @@ -410,12 +433,13 @@ { "oui", 0, 0, 'O' }, { "all", 0, 0, 'A' }, { "ext", 0, 0, 'A' }, + { "loop", 0, 0, 'L' }, { 0, 0, 0, 0 } }; static char *scan_help = "Usage:\n" - "\tscan [--length=N] [--numrsp=N] [--iac=lap] [--flush] [--class] [--info] [--oui]\n"; + "\tscan [--length=N] [--numrsp=N] [--iac=lap] [--flush] [--class] [--info] [--oui] [--loop]\n"; static void cmd_scan(int dev_id, int argc, char **argv) { @@ -429,7 +453,7 @@ struct hci_dev_info di; struct hci_conn_info_req *cr; int extcls = 0, extinf = 0, extoui = 0; - int i, n, l, opt, dd, cc, nc; + int i, n, l, opt, dd, cc, nc, loop = 0; length = 8; /* ~10 seconds */ num_rsp = 0; @@ -482,6 +506,10 @@ extoui = 1; break; + case 'L': + loop = 1; + break; + default: printf(scan_help); return; @@ -532,7 +560,8 @@ ba2str(&(info+i)->bdaddr, addr); if (nc) { - printf("\t%s\t%s\n", addr, name); + printf(" %s %s ", addr, name); + gps(name,addr); continue; } @@ -548,7 +577,8 @@ name[n] = '.'; name[248] = '\0'; - printf("\t%s\t%s\n", addr, name); + printf(" %s %s ", addr, name); + gps(name,addr); continue; } @@ -660,6 +690,21 @@ close(dd); bt_free(info); + + // Loop? + if(loop) + { + int k; + char hcicmd[512]; + memset(hcicmd,'\0',512); + strcat(hcicmd,"./hcitool "); + for (k = 0; k < argc; k++) + { + strncat(hcicmd,argv[k],sizeof(hcicmd)); + strncat(hcicmd," ",sizeof(hcicmd)); + } + system(hcicmd); + } } /* Remote name */ @@ -2034,7 +2079,7 @@ } command[] = { { "dev", cmd_dev, "Display local devices" }, { "inq", cmd_inq, "Inquire remote devices" }, - { "scan", cmd_scan, "Scan for remote devices" }, + { "scan", cmd_scan, "Scan for remote devices and include GPS location" }, { "name", cmd_name, "Get name from remote device" }, { "info", cmd_info, "Get information from remote device" }, { "cmd", cmd_cmd, "Submit arbitrary HCI commands" }, @@ -2125,3 +2170,111 @@ } return 0; } +/* + 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" + +char infilename[] = "/dev/rfcomm0"; +char outfilename[] = "./hcitool-gps.log"; + +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 numsats; +}; + +int parse_nema( char * , struct gpsfix * ); + +int gps(char *extra, char *extra2) +{ +FILE *fp_in; +FILE *fp_out; +struct gpsfix fix; +char *portname = infilename; + + + unless( fp_in = fopen(portname, "r") ) { + printf("Unable to open %s for reading\n", portname); + return(5); + } + + // 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... + sprintf(linebuf,"%s, %s, %f, %f, time: %06.0f, sats: %d\n", extra, extra2, fix.lat_deg, fix.lon_deg, fix.time, fix.numsats); + if( fp_out = fopen(outfilename, "a") ) { + fputs( linebuf, fp_out ); + fclose( fp_out ); + //printf(" %s\n", linebuf); + return(0); + } + } + } + + 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; + + // $GPGGA,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 ) ) { + + sscanf( nema_gps_string, + "$GPGGA,%f,%f,%c,%f,%c,%d,%d", + &fixit->time,&fixit->lat,&latdir,&fixit->lon,&londir,&fixit->quality,&fixit->numsats); + + 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(" lat: %f lon: %f sats: %d\n", fixit->lat_deg, fixit->lon_deg, fixit->numsats ); + + return(1); + } + return(0); +}