cgps.c

来自「gpsd, a popular GPS daemon.」· C语言 代码 · 共 843 行 · 第 1/2 页

C
843
字号
    } else {      n=0;      for (i = 0; i < MAX_POSSIBLE_SATS; i++) {	if (n < display_sats) {	  if ((i < gpsdata->satellites) && ((gpsdata->used[i]!=0) || (gpsdata->satellites <= display_sats))) {	      (void)snprintf(scr, sizeof(scr),			  " %3d    %02d    %03d    %02d      %c",			  gpsdata->PRN[i],			  gpsdata->elevation[i], gpsdata->azimuth[i],			  gpsdata->ss[i], gpsdata->used[i] ? 'Y' : 'N');	    (void)mvwprintw(satellites, n+2, 1, "%-*s", SATELLITES_WIDTH - 3, scr);	    n++;	  }	}      }      if(n < display_sats) {	for (i = n; i <= display_sats; i++) {	  (void)mvwprintw(satellites, i+2, 1, "%-*s", SATELLITES_WIDTH - 3, "");	}      }    }  }  /* Print time/date. */  if (isnan(gpsdata->fix.time)==0) {    (void)unix_to_iso8601(gpsdata->fix.time, scr, sizeof(scr));  } else    (void)snprintf(scr, sizeof(scr), "n/a");  (void)mvwprintw(datawin, 1, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);  /* Fill in the latitude. */  if (gpsdata->fix.mode >= MODE_2D && isnan(gpsdata->fix.latitude)==0) {    (void)snprintf(scr, sizeof(scr), "%s %c",          deg_to_str(deg_type,  fabs(gpsdata->fix.latitude)),          (gpsdata->fix.latitude < 0) ? 'S' : 'N');  } else    (void)snprintf(scr, sizeof(scr), "n/a");  (void)mvwprintw(datawin, 2, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);  /* Fill in the longitude. */  if (gpsdata->fix.mode >= MODE_2D && isnan(gpsdata->fix.longitude)==0) {    (void)snprintf(scr, sizeof(scr), "%s %c",          deg_to_str(deg_type,  fabs(gpsdata->fix.longitude)),          (gpsdata->fix.longitude < 0) ? 'W' : 'E');  } else    (void)snprintf(scr, sizeof(scr), "n/a");  (void)mvwprintw(datawin, 3, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);  /* Fill in the altitude. */  if (gpsdata->fix.mode == MODE_3D && isnan(gpsdata->fix.altitude)==0)    (void)snprintf(scr, sizeof(scr), "%.1f %s",gpsdata->fix.altitude*altfactor, altunits);  else    (void)snprintf(scr, sizeof(scr), "n/a");  (void)mvwprintw(datawin, 4, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);  /* Fill in the speed. */  if (gpsdata->fix.mode >= MODE_2D && isnan(gpsdata->fix.track)==0)    (void)snprintf(scr, sizeof(scr), "%.1f %s", gpsdata->fix.speed*speedfactor, speedunits);  else    (void)snprintf(scr, sizeof(scr), "n/a");  (void)mvwprintw(datawin, 5, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);  /* Fill in the heading. */  if (gpsdata->fix.mode >= MODE_2D && isnan(gpsdata->fix.track)==0)    (void)snprintf(scr, sizeof(scr), "%.1f degrees", gpsdata->fix.track);  else    (void)snprintf(scr, sizeof(scr), "n/a");  (void)mvwprintw(datawin, 6, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);  /* Fill in the rate of climb. */  if (gpsdata->fix.mode == MODE_3D && isnan(gpsdata->fix.climb)==0)    (void)snprintf(scr, sizeof(scr), "%.1f %s/min",	gpsdata->fix.climb * altfactor * 60, altunits);  else    (void)snprintf(scr, sizeof(scr), "n/a");  (void)mvwprintw(datawin, 7, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);  /* Fill in the GPS status and the time since the last state     change. */  if (gpsdata->online == 0) {    newstate = 0;    (void)snprintf(scr, sizeof(scr), "OFFLINE");  } else {    newstate = gpsdata->fix.mode;    switch (gpsdata->fix.mode) {    case MODE_2D:      (void)snprintf(scr, sizeof(scr), "2D %sFIX (%d secs)",(gpsdata->status==STATUS_DGPS_FIX)?"DIFF ":"", (int) (time(NULL) - status_timer));      break;    case MODE_3D:      (void)snprintf(scr, sizeof(scr), "3D %sFIX (%d secs)",(gpsdata->status==STATUS_DGPS_FIX)?"DIFF ":"", (int) (time(NULL) - status_timer));      break;    default:      (void)snprintf(scr, sizeof(scr), "NO FIX (%d secs)", (int) (time(NULL) - status_timer));      break;    }  }  (void)mvwprintw(datawin, 8, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);  /* Fill in the receiver type. */  if(got_gps_type==1) {    (void)snprintf(scr, sizeof(scr), "%s",gps_type);  } else {    (void)snprintf(scr, sizeof(scr), "unknown");  }  (void)mvwprintw(datawin, 9, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);    /* Note that the following four fields are exceptions to the       sizing rule.  The minimum window size does not include these       fields, if the window is too small, they get excluded.  This       may or may not change if/when the output for these fields is       fixed and/or people request their permanance.  They're only       there in the first place because I arbitrarily thought they       sounded interesting. ;^) */    if(window_length >= (MIN_GPS_DATAWIN_SIZE + 4)) {      /* Fill in the estimated horizontal position error. */      if (isnan(gpsdata->fix.eph)==0)	(void)snprintf(scr, sizeof(scr), "+/- %d %s", (int) (gpsdata->fix.eph * altfactor), altunits);      else        (void)snprintf(scr, sizeof(scr), "n/a");      (void)mvwprintw(datawin, 10, DATAWIN_VALUE_OFFSET + 5, "%-*s", 22, scr);      /* Fill in the estimated vertical position error. */      if (isnan(gpsdata->fix.epv)==0)	(void)snprintf(scr, sizeof(scr), "+/- %d %s", (int)(gpsdata->fix.epv * altfactor), altunits);      else        (void)snprintf(scr, sizeof(scr), "n/a");      (void)mvwprintw(datawin, 11, DATAWIN_VALUE_OFFSET + 5, "%-*s", 22, scr);      /* Fill in the estimated track error. */      if (isnan(gpsdata->fix.epd)==0)	(void)snprintf(scr, sizeof(scr), "+/- %.1f deg", (gpsdata->fix.epd));      else        (void)snprintf(scr, sizeof(scr), "n/a");      (void)mvwprintw(datawin, 12, DATAWIN_VALUE_OFFSET + 5, "%-*s", 22, scr);      /* Fill in the estimated speed error. */      if (isnan(gpsdata->fix.eps)==0)	(void)snprintf(scr, sizeof(scr), "+/- %d %s", (int)(gpsdata->fix.eps * speedfactor), speedunits);      else        (void)snprintf(scr, sizeof(scr), "n/a");      (void)mvwprintw(datawin, 13, DATAWIN_VALUE_OFFSET + 5, "%-*s", 22, scr);    }  /* Be quiet if the user requests silence. */  if(silent_flag==0 && raw_flag==1) {    (void)wprintw(messages, "%s\n", message);  }  /* Reset the status_timer if the state has changed. */  if (newstate != state) {    status_timer = time(NULL);    state = newstate;  }  (void)wrefresh(datawin);  (void)wrefresh(satellites);  if(raw_flag==1) {    (void)wrefresh(messages);  }}static void usage( char *prog){  (void)fprintf(stderr,		"Usage: %s [-h] [-V] [-l {d|m|s}] [server[:port:[device]]]\n\n"		"  -h	  Show this help, then exit\n"		"  -V	  Show version, then exit\n"		"  -s	  Be silent (don't print raw gpsd data)\n"		"  -l {d|m|s}  Select lat/lon format\n"		"		d = DD.dddddd\n"		"		m = DD MM.mmmm'\n"		"		s = DD MM' SS.sss\"\n"		, prog);  exit(1);}int main(int argc, char *argv[]){  int option;  char *arg = NULL, *colon1, *colon2, *device = NULL, *server = NULL, *port = DEFAULT_GPSD_PORT;  char *err_str = NULL;  int c;  struct timeval timeout;  fd_set rfds;  int data;  /* Process the options.  Print help if requested. */  while ((option = getopt(argc, argv, "hVl:sj")) != -1) {    switch (option) {    case 's':      silent_flag=1;      break;    case 'j':      fixclear_flag=1;      break;    case 'V':      (void)fprintf(stderr, "SVN ID: $Id: cgps.c 4547 2007-12-13 01:38:22Z esr $ \n");      exit(0);    case 'l':      switch ( optarg[0] ) {      case 'd':	deg_type = deg_dd;	continue;      case 'm':	deg_type = deg_ddmm;	continue;      case 's':	deg_type = deg_ddmmss;	continue;      default:	(void)fprintf(stderr, "Unknown -l argument: %s\n", optarg);	/*@ -casebreak @*/      }    case 'h': default:      usage(argv[0]);      break;    }  }  /* Grok the server, port, and device. */  /*@ -branchstate @*/  if (optind < argc) {    arg = strdup(argv[optind]);    /*@i@*/colon1 = strchr(arg, ':');    server = arg;    if (colon1 != NULL) {      if (colon1 == arg)	server = NULL;      else	*colon1 = '\0';      port = colon1 + 1;      colon2 = strchr(port, ':');      if (colon2 != NULL) {	if (colon2 == port)	  port = NULL;	else	  *colon2 = '\0';	device = colon2 + 1;      }    }    colon1 = colon2 = NULL;  }  /*@ +branchstate @*/  /*@ -observertrans @*/  switch (gpsd_units())    {    case imperial:      altfactor = METERS_TO_FEET;      altunits = "ft";      speedfactor = MPS_TO_MPH;      speedunits = "mph";      break;    case nautical:      altfactor = METERS_TO_FEET;      altunits = "ft";      speedfactor = MPS_TO_KNOTS;      speedunits = "knots";      break;    case metric:      altfactor = 1;      altunits = "m";      speedfactor = MPS_TO_KPH;      speedunits = "kph";      break;    default:      /* leave the default alone */      break;    }  /*@ +observertrans @*/  /* Open the stream to gpsd. */  /*@i@*/gpsdata = gps_open(server, port);  if (!gpsdata) {    switch ( errno ) {    case NL_NOSERVICE:  err_str = "can't get service entry"; break;    case NL_NOHOST:     err_str = "can't get host entry"; break;    case NL_NOPROTO:    err_str = "can't get protocol entry"; break;    case NL_NOSOCK:     err_str = "can't create socket"; break;    case NL_NOSOCKOPT:  err_str = "error SETSOCKOPT SO_REUSEADDR"; break;    case NL_NOCONNECT:  err_str = "can't connect to host"; break;    default:		    err_str = "Unknown"; break;    }    (void)fprintf( stderr,		   "cgps: no gpsd running or network error: %d, %s\n",		   errno, err_str);    exit(2);  }  /* Set both timers to now. */  status_timer = time(NULL);  misc_timer = status_timer;  /* If the user requested a specific device, try to change to it. */  if (device)      (void)gps_query(gpsdata, "F=%s\n", device);  /* Here's where updates go until we figure out what we're dealing     with. */  gps_set_raw_hook(gpsdata, update_probe);  /* Tell me what you are... */  (void)gps_query(gpsdata, "i\n");  /* Loop for ten seconds looking for a device.  If none found, give     up and assume "unknown" device type. */  while(got_gps_type==0) {    /* Sleep for one second. */    timeout.tv_sec = 1;    timeout.tv_usec = 0;    (int)select(0,NULL,NULL,NULL,&timeout);    /* Give up after ten seconds. */    if(time(NULL)-status_timer >= 10) {      (void)strlcpy(gps_type, "unknown", sizeof(gps_type));      got_gps_type=1;    }  }  /* If the user has requested the 'j' option (buffering), make the     request of gpsd before we continue. */  if(fixclear_flag==1 && compass_flag==0) {    (void)gps_query(gpsdata, "j=1\n");  }  /* Fire up curses. */  (void)initscr();  (void)noecho();  (void)signal(SIGINT,die);  (void)signal(SIGHUP,die);  windowsetup();  /* Here's where updates go now that things are established. */  if(compass_flag==1) {    gps_set_raw_hook(gpsdata, update_compass_panel);  } else {    gps_set_raw_hook(gpsdata, update_gps_panel);  }  /* Request "w+x" data from gpsd. */  (void)gps_query(gpsdata, "w+x\n");  /* heart of the client */  for (;;) {    /* watch to see when it has input */    FD_ZERO(&rfds);    FD_SET(gpsdata->gps_fd, &rfds);    /* wait up to five seconds. */    timeout.tv_sec = 5;    timeout.tv_usec = 0;    /* check if we have new information */    data = select(gpsdata->gps_fd + 1, &rfds, NULL, NULL, &timeout);    if (data == -1) {      fprintf( stderr, "cgps: socket error\n");      exit(2);    }    else if( data ) {      /* code that calls gps_poll(gpsdata) */      if (gps_poll(gpsdata) != 0)	die(1);    }    /* Check for user input.     TODO: Restrict the allowed keys based on device type (ie, 'j'     makes no sense for a True North compass).  No doubt there will be     other examples as cgps grows more bells and whistles. */    c=wgetch(datawin);    switch ( c ) {      /* Quit */    case 'q':      die(0);      break;      /* Toggle spewage of raw gpsd data. */    case 's':      if(silent_flag==0) {	silent_flag=1;      } else {	silent_flag=0;      }      break;      /* Toggle fix clear. */    case 'j':      if(fixclear_flag==0) {	fixclear_flag=1;	(void)gps_query(gpsdata, "j=1\n");      } else {	fixclear_flag=0;	(void)gps_query(gpsdata, "j=0\n");      }      break;      /* Clear the spewage area. */    case 'c':      (void)werase(messages);      break;    default:      break;    }  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?