/* Makes a simple HTML and SVG layout for GPSD */ /* (C)2007 Jason Hecker v0.03*/ /* This is a severely mangled version of xgps.c */ /* To use call: webgps [server] [port] [path] [period] */ /* server: the gpsd server you are connecting to */ /* port: the port number of the gpsd server */ /* path: the destination path for gpsd.svg/html */ /* period: time period in seconds for webgps to update */ #include #include #include #include #include #include #include #include /* v2.33 */ #include "config.h" /* v2.34+ */ //#include "gpsd_config.h" #include "gps.h" #define TRACKMAX 1024 #define SATMAX 20 #define STALECOUNT 3 typedef struct trackloc_s{ int x; int y; } trackloc_t; typedef struct trackloc_head_s{ int PRN; int count; int stale; trackloc_t posn[TRACKMAX]; } trackloc_head_t; trackloc_head_t sattrack[SATMAX]; static enum deg_str_type deg_type = deg_dd; static struct gps_data_t *gpsdata; static time_t timer; /* time of last state change */ static int state = 0; /* or MODE_NO_FIX=1, MODE_2D=2, MODE_3D=3 */ void do_html(FILE *fh); void do_svg(FILE *fs); void polartocart(int *x, int *y, int el, int az){ #define DEG2RAD PI/180.0 #define DIAMETER 200 #define XYOFFSET 10 float radius, theta; radius = DIAMETER * cos(((float)(el)) * DEG2RAD); theta = ((float)(az - 90) * DEG2RAD); *x = (int)(radius * cos(theta) + 0.5) + DIAMETER + XYOFFSET; *y = (int)(radius * sin(theta) + 0.5) + DIAMETER + XYOFFSET; } void do_html(FILE *fh){ int i, newstate; char s[128], *latlon; const char pageheader[] = "\n" \ "\t\n\tGPSD Satellite Positions and Readings\n\t\n\n" \ "\n\t\n"); /* SVG Stuff */ fprintf(fh,"\t\n"); fprintf(fh,"
\n\t\t\n" "\t\t\t\n\t\t\t\t" "\n\t\t\t\n"; const char rowhead[] = "\t\t\t\n\t\t\t\t\n\t\t\t\n"; fprintf(fh,pageheader); if (gpsdata->satellites) { for (i = 0; i < MAXCHANNELS; i++) { if (i < (unsigned int)gpsdata->satellites) { fprintf(fh,"\t\t\t\n\t\t\t\t\n\t\t\t\n", gpsdata->PRN[i], gpsdata->elevation[i], gpsdata->azimuth[i], gpsdata->ss[i], gpsdata->used[i] ? 'Y' : 'N'); } } } fprintf(fh,"\t\t
PRN:Elev:Azim:SNR:Used:
%s%s
%3d%2d%3d%2d%c
\n"); fprintf(fh,"\t\t\n"); if (isnan(gpsdata->fix.time)==0) { (void)unix_to_iso8601(gpsdata->fix.time, s, (int)sizeof(s)); } else (void)strcpy(s,"n/a"); fprintf(fh,rowhead,"Time:",s); if (gpsdata->fix.mode >= MODE_2D) { latlon = deg_to_str(deg_type, fabs(gpsdata->fix.latitude)); (void)snprintf(s, sizeof(s), "%s %c", latlon, (gpsdata->fix.latitude < 0) ? 'S' : 'N'); } else (void)strcpy(s, "n/a"); fprintf(fh,rowhead,"Latitude:",s); if (gpsdata->fix.mode >= MODE_2D) { latlon = deg_to_str(deg_type, fabs(gpsdata->fix.longitude)); (void)snprintf(s, sizeof(s), "%s %c", latlon, (gpsdata->fix.longitude < 0) ? 'W' : 'E'); } else (void)strcpy(s, "n/a"); fprintf(fh,rowhead,"Longitude:",s); if (gpsdata->fix.mode == MODE_3D) { (void)snprintf(s, sizeof(s), "%f metres", gpsdata->fix.altitude); } else (void)strcpy(s, "n/a"); fprintf(fh,rowhead,"Altitude:",s); if (gpsdata->fix.mode >= MODE_2D && isnan(gpsdata->fix.track)==0) { (void)snprintf(s, sizeof(s), "%f metres/sec", gpsdata->fix.speed); } else (void)strcpy(s, "n/a"); fprintf(fh,rowhead,"Speed:",s); if (gpsdata->fix.mode >= MODE_2D && isnan(gpsdata->fix.track)==0) { (void)snprintf(s, sizeof(s), "%f degrees", gpsdata->fix.track); } else (void)strcpy(s, "n/a"); fprintf(fh,rowhead,"Course:",s); if (isnan(gpsdata->fix.eph)==0) { (void)snprintf(s, sizeof(s), "%f metres", gpsdata->fix.eph); } else (void)strcpy(s, "n/a"); fprintf(fh,rowhead,"EPH:",s); if (isnan(gpsdata->fix.epv)==0) { (void)snprintf(s, sizeof(s), "%f metres", gpsdata->fix.epv); } else (void)strcpy(s, "n/a"); fprintf(fh,rowhead,"EPV:",s); if (gpsdata->fix.mode == MODE_3D && isnan(gpsdata->fix.climb)==0) { (void)snprintf(s, sizeof(s), "%f metres/sec", gpsdata->fix.climb); } else (void)strcpy(s, "n/a"); fprintf(fh,rowhead,"Climb:",s); if (gpsdata->online == 0) { newstate = 0; (void)snprintf(s, sizeof(s), "OFFLINE"); } else { newstate = gpsdata->fix.mode; switch (gpsdata->fix.mode) { case MODE_2D: (void)snprintf(s, sizeof(s), "2D %sFIX",(gpsdata->status==STATUS_DGPS_FIX)?"DIFF ":""); break; case MODE_3D: (void)snprintf(s, sizeof(s), "3D %sFIX",(gpsdata->status==STATUS_DGPS_FIX)?"DIFF ":""); break; default: (void)snprintf(s, sizeof(s), "NO FIX"); break; } } if (newstate != state) { timer = time(NULL); state = newstate; } (void)snprintf(s+strlen(s), sizeof(s)-strlen(s), " (%d secs)", (int) (time(NULL) - timer)); fprintf(fh,"\t\t\t\n\t\t\t\t\n\t\t\t\n",s); fprintf(fh,"\t\t
State%s
\n\t
\n\t\t\n"); //fprintf(fh,"\t\n\t\t\n\t
\n\n\n"); } void do_svg(FILE *fs){ int i, j, x, y, offset; char *fill; const char svghead[] = "\n" \ "\n" \ "\n" \ "\t\n" \ "\t\t\n" \ "\t\t\n" \ "\t\t\n" \ "\t\t\n" \ "\t\t\n" \ "\t\t\n" \ "\t\t\n" \ "\t\t\n" \ "\t\t\tN\n" \ "\t\t\tW\n" \ "\t\t\tE\n" \ "\t\t\tS\n"; /* Draw the chart axes */ fprintf(fs, svghead); /* Draw the skid marks */ //printf("Skidin\n"); for(i=0;i 1){ fprintf(fs,"\t\t\t\n"); } } } //printf("Skidout\n"); /* Draw the birdies */ if (gpsdata->satellites) { for (i = 0; i < MAXCHANNELS; i++) { if (i < (unsigned int)gpsdata->satellites) { polartocart(&x , &y, gpsdata->elevation[i], gpsdata->azimuth[i]); if(gpsdata->ss[i] < 30) fill = "\"silver\""; else if (gpsdata->ss[i] < 40) fill = "\"yellow\""; else fill = "\"lime\""; /* Centre single digits PRNs in the circle */ if(gpsdata->PRN[i] < 10) offset = 3; else offset = 0; fprintf(fs,"\t\t\t\n",fill); fprintf(fs,"\t\t\t%d\n",x-6+offset,y+4,gpsdata->PRN[i]); } } } fprintf(fs,"\t\t\n"); fprintf(fs,"\t\n"); fprintf(fs,"\n"); } /* Initialise the track table */ void init_track_table(void){ int i; //printf("ITT\n"); for (i=0; isatellites) { for (i = 0; i < MAXCHANNELS; i++) { if (i < (unsigned int)gpsdata->satellites) { polartocart(&x , &y, gpsdata->elevation[i], gpsdata->azimuth[i]); insert_sat(gpsdata->PRN[i],x,y); } } } delete_stale_sats(); } int main(int argc, char *argv[]) { FILE *fh,*fs = NULL; char *err_str = NULL; //char server[] = "gpsd.mainframe.cx"; //char port[] = "2947"; char *server; char *port; char *path; int period; char name1[256], name2[256]; //printf("argc %d\n",argc); if (argc != 5){ fprintf(stderr,"Not enough arguments: \n"); exit(2); } server = argv[1]; port = argv[2]; path = argv[3]; period = atoi(argv[4]); 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, "xgps: no gpsd running or network error: %d, %s\n", errno, err_str); exit(2); } init_track_table(); (void)gps_query(gpsdata, "w+x"); (void)gps_query(gpsdata, "j=1"); for(;;){ (void)gps_poll(gpsdata); update_track_table(); sprintf(name1,"%s/gpsd.html",path); sprintf(name2,"%s/gpsd.svg",path); if((fh=fopen(name1,"w")) != NULL ){ do_html(fh); fclose(fh); } if((fs=fopen(name2,"w")) != NULL ){ do_svg(fs); fclose(fs); } sleep(period); } return(0); }