PHP Classes
elePHPant
Icontem

File: dir/webgps.c.txt

Recommend this page to a friend!
  Classes of Uku-Kaarel Jo~esaar  >  finfo  >  dir/webgps.c.txt  >  Download  
File: dir/webgps.c.txt
Role: Documentation
Content type: text/plain
Description: Documentation
Class: finfo
Determine the type of files analyzing its contents
Author: By
Last change:
Date: 2 years ago
Size: 13,709 bytes
 

 

Contents

Class file image Download
/* 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 <stdio.h>
#include <math.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <math.h>

/* 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[] = "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" \
                              "\t<head>\n\t<title>GPSD Satellite Positions and Readings</title>\n\t</head>\n<body>\n" \
                              "<table border=\"1\">\n\t<td>\n\t\t<table border=\"0\">\n"
                              "\t\t\t<tr>\n\t\t\t\t<td><b>PRN:</b></td><td><b>Elev:</b></td><td><b>Azim:</b></td>"
                              "<td><b>SNR:</b></td><td><b>Used:</b></td>\n\t\t\t</tr>\n";
    
    const char rowhead[] = "\t\t\t<tr>\n\t\t\t\t<td><b>%s</b></d><td>%s</td>\n\t\t\t</tr>\n";
    
    fprintf(fh,pageheader);
    
    if (gpsdata->satellites) {
        for (i = 0; i < MAXCHANNELS; i++) {
            if (i < (unsigned int)gpsdata->satellites) {
                fprintf(fh,"\t\t\t<tr>\n\t\t\t\t<td>%3d</td><td>%2d</td><td>%3d</td><td>%2d</td><td>%c</td>\n\t\t\t</tr>\n",
                        gpsdata->PRN[i],
                        gpsdata->elevation[i], gpsdata->azimuth[i], 
                        gpsdata->ss[i],	gpsdata->used[i] ? 'Y' : 'N');
            }
        }
    }
    
    fprintf(fh,"\t\t</table>\n");

    fprintf(fh,"\t\t<table border=\"0\">\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<tr>\n\t\t\t\t<td><b>State</b></d><td>%s</td>\n\t\t\t</tr>\n",s);
    
    fprintf(fh,"\t\t</table>\n\t</td>\n");

    /* SVG Stuff */
    fprintf(fh,"\t<td>\n\t\t<embed src=\"gpsd.svg\" width=\"425\" height=\"425\" type=\"image/svg+xml\">\n");
    
    //fprintf(fh,"\t<td>\n\t\t<object data=\"gpsd.svg\" width=\"425\" height=\"425\" align=\"center\"\n");
    //fprintf(fh,"\t\t\ttype=\"image/svg+xml\"\n\t\t\tcodebase=\"http://www.adobe.com/svg/viewer/install/\" />\n\t</td>\n");
    
    fprintf(fh,"</table>\n\n</body>\n</html>");
    
    
}


void do_svg(FILE *fs){
    
    int i, j, x, y, offset;
    char *fill;
    
    const char svghead[] = "<?xml version=\"1.0\" standalone=\"no\"?>\n" \
    "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n" \
    "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n" \
    "<svg width=\"100%%\" height=\"100%%\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n" \
    "\t<g transform=\"translate(00,0)\">\n" \
    "\t\t<circle cx=\"210\" cy=\"210\" r=\"200\" stroke=\"black\"\n" \
    "\t\tstroke-width=\"1\" fill=\"white\"/>\n" \
    "\t\t<circle cx=\"210\" cy=\"210\" r=\"100\" stroke=\"grey\"\n" \
    "\t\tstroke-width=\"1\" fill=\"white\"/>\n" \
    "\t\t<circle cx=\"210\" cy=\"210\" r=\"2\" stroke=\"grey\"\n" \
    "\t\tstroke-width=\"1\" fill=\"white\"/>\n" \
    "\t\t<line x1=\"210\" y1=\"10\" x2=\"210\" y2=\"410\" stroke=\"lightgrey\" />\n" \
    "\t\t<line x1=\"10\" y1=\"210\" x2=\"410\" y2=\"210\" stroke=\"lightgrey\" />\n" \
    "\t\t<line x1=\"68.578644\" y1=\"68.578644\" x2=\"351.42136\" y2=\"351.42136\" stroke=\"lightgrey\" />\n" \
    "\t\t<line x1=\"68.578644\" y1=\"351.42136\" x2=\"351.42136\" y2=\"68.578644\" stroke=\"lightgrey\" />\n" \
    "\t\t<g font-size=\"10\" stroke=\"black\" stroke-width=\"0.5\">\n" \
    "\t\t\t<text x=\"206\" y=\"8\">N</text>\n" \
    "\t\t\t<text x=\"0\" y=\"214\">W</text>\n" \
    "\t\t\t<text x=\"412\" y=\"214\">E</text>\n" \
    "\t\t\t<text x=\"206\" y=\"420\">S</text>\n";

    /* Draw the chart axes */
    fprintf(fs, svghead);
    
    /* Draw the skid marks */
    //printf("Skidin\n");
    for(i=0;i<SATMAX;i++){
        if(sattrack[i].PRN != -1){
            if(sattrack[i].count > 1){
                fprintf(fs,"\t\t\t<polyline stroke-width=\"0.6\" stroke=\"red\" fill=\"none\" points=\"");
                for(j=0;j <= sattrack[i].count-1;j++){
                    x = sattrack[i].posn[j].x;
                    y = sattrack[i].posn[j].y;
                    fprintf(fs,"%d,%d ", x, y);
                }
                fprintf(fs,"\"/>\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<circle cx=\"%d\" cy=\"%d\" r=\"8\" stroke=\"black\"\n",x,y);
                fprintf(fs,"\t\t\t\tstroke-width=\"1\" fill=%s/>\n",fill);
                fprintf(fs,"\t\t\t<text x=\"%d\" y=\"%d\" stroke=\"black\" fill=\"black\" " \
                           "font-size=\"10\">%d</text>\n",x-6+offset,y+4,gpsdata->PRN[i]);
            }
        }
    }
    

    fprintf(fs,"\t\t</g>\n");
    fprintf(fs,"\t</g>\n");
    fprintf(fs,"</svg>\n");
}

/* Initialise the track table */
void init_track_table(void){
    
    int i;
    
    //printf("ITT\n");

    for (i=0; i<SATMAX; i++){
        sattrack[i].PRN = -1;
        sattrack[i].count = 0;
        sattrack[i].stale = 0;
    }
}

/* Make all tracks stale */
void make_tracks_stale(void){
    
    int i;
    //printf("MTS\n"); 
    for(i=0; i<SATMAX; i++){
        if(sattrack[i].stale != 0)
            sattrack[i].stale--;
    }
}

/* Returns the index the PRN is in -  -1 is a fail*/
int exists_in_table(int prn){

    int i;
    //printf("EIT\n");
    for(i=0; i< SATMAX; i++){
        if (sattrack[i].PRN == prn)
            return(i);
    }
    
    return -1;
}

/* Inserts a new sat xy entry into the table */
void insert_sat(int prn, int x, int y){
    
    int i, idx;

    idx = exists_in_table(prn);
    
    if (idx == -1){
        for(i=0; i<SATMAX; i++){
            if(sattrack[i].PRN == -1){
                sattrack[i].PRN = prn;
                sattrack[i].posn[0].x = x;
                sattrack[i].posn[0].y = y;
                sattrack[i].count = 1;
                sattrack[i].stale = STALECOUNT;
                
            }
        }
    }
    else{
        if(sattrack[idx].count < (TRACKMAX-1)){
            if(sattrack[idx].posn[sattrack[idx].count-1].x != x || \
                sattrack[idx].posn[sattrack[idx].count-1].y != y){
                sattrack[idx].posn[sattrack[idx].count].x = x;
                sattrack[idx].posn[sattrack[idx].count].y = y;
                sattrack[idx].count++;
            }
            sattrack[idx].stale = STALECOUNT;
        }
    }
    //printf("IS %d %d %d\n",idx,prn,sattrack[idx].count);

}

/* Deletes stale sats */
void delete_stale_sats(void){
    
    int i;
    
    //printf("DSS\n");
    
    for(i=0; i<SATMAX; i++){
        if (sattrack[i].stale == 0){
            sattrack[i].PRN = -1;
            sattrack[i].count = 0;
        }
    }
    //printf("DSSO\n");
}

void update_track_table(void){

    int i, x, y;
    
    //printf("UTT\n");
   
    make_tracks_stale();
    
    if (gpsdata->satellites) {
        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: <server> <port> <path> <period>\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);
}