Changeset 831

Show
Ignore:
Timestamp:
07/27/07 11:25:16 (16 months ago)
Author:
michael
Message:

GPS plugin update by michu

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/plugin_gps.c

    r801 r831  
    22 * $URL$ 
    33 * 
    4  * gps plugin, code by michu / www.neophob.com, based on nmeap, http://sourceforge.net/projects/nmeap/ 
     4 * gps plugin (nmea), code by michu / www.neophob.com, based on nmeap, http://sourceforge.net/projects/nmeap/ 
    55 * 
    66 * Copyright (C) 2007 michu 
     
    2626 
    2727/*  
    28  * exported functions: 
    29  * 
    30  * int plugin_init_gps (void) 
    31  *  adds various functions 
    32  * 
     28 * GPS Plugin for lcd4linux, by michael vogt / http://www.neophob.com 
     29 * contact: michu@neophob.com 
     30 * 
     31 * based on nmeap by daveh, http://www.dmh2000.com/ or http://sourceforge.net/projects/nmeap/ 
     32 * you need a compiled libnmeap to compile this plugin. 
     33 * 
     34 * History: 
     35 *  v0.1 initial release 
     36 * 
     37 * TODO: 
     38 *  -update direction only when speed > 5 kmh 
     39 *  -add more data fields 
     40 *  -dump nmea string to external file 
     41 * 
     42 * Exported functions: 
     43 * int plugin_init_gps (void) - default plugin initialisation 
     44 * void parse(SHOW-OPTIONS, DISPLAY-OPTIONS) 
     45 *  display option define, what the plugin should display 
     46 * 
     47 *  OPTION:           EXAMPLE: 
     48 *  -------           -------- 
     49 * 
     50 * PARAMETER 1: 
     51 *  #define SHOW_ALTITUDE     0x000000001 alt:500 
     52 *  #define SHOW_SPEED    0x000000010 spd:30 
     53 *  #define SHOW_COURSE     0x000000100 dir:NO 
     54 *  #define SHOW_SATELLITES   0x000001000 sat:4 
     55 *  #define SHOW_QUALITY    0x000010000 qua:1 
     56 *  #define SHOW_STATUS     0x000100000 sta:V 
     57 *  #define SHOW_TIME_UTC     0x001000000 utc:113459 
     58 *  #define SHOW_DATE     0x010000000 dat:190204 (19.02.2004) 
     59 * 
     60 * PARAMETER 2:  
     61 *  #define DISPLAY_NO_PREFIX   0x000000001 disable prefix (example, instead of "alt:500" it displays "500" 
     62 *  #define DISPLAY_SPEED_IN_KNOTS  0x000000010 when use the SHOW_SPEED option, display speed in knots instead in km/h 
     63 * 
     64 *  Examples:   
     65 *    - gps::parse('0x011','0') will display the altitude and speed -> alt:500 spd:43 
     66 *    - gps::parse('0x01100','0') will display the course and the numbers of satellites -> dir:NO sat:3 
     67 *    - gps::parse('0x01','0x01') will display the speed without prefix -> 50 
     68 *    - gps::parse('0x01','0x01') will display the speed in knots without prefix -> 27 
    3369 */ 
    3470 
     
    4278#include <ctype.h> 
    4379#include <unistd.h> 
    44 #include <fcntl.h> 
    45 #include <termios.h> 
    46 #include <errno.h> 
    47 #include <sys/types.h> 
    48 #include <sys/stat.h> 
    49 #include <sys/ioctl.h> 
    50 #include <sys/io.h> 
    5180 
    5281/* these should always be included */ 
     
    6089#include "nmeap.h" 
    6190 
    62  
    63 #define SHOW_ALTITUDE   0x0000001 
    64 #define SHOW_SPEED  0x0000010 
    65 #define SHOW_COURSE   0x0000100 
    66 #define SHOW_SATELLITES 0x0001000 
    67 #define SHOW_QUALITY  0x0010000 
    68 #define SHOW_WARN   0x0100000 
    69  
    70 nmeap_gga_t g_gga; 
    71  
    72  
     91//#define EMULATE                       //remove comment to enable gps data emulation... 
     92 
     93#define SHOW_ALTITUDE     0x000000001 
     94#define SHOW_SPEED    0x000000010 
     95#define SHOW_COURSE     0x000000100 
     96#define SHOW_SATELLITES   0x000001000 
     97#define SHOW_QUALITY    0x000010000 
     98#define SHOW_STATUS     0x000100000 
     99#define SHOW_TIME_UTC     0x001000000 
     100#define SHOW_DATE     0x010000000 
     101 
     102#define DISPLAY_NO_PREFIX   0x000000001 
     103#define DISPLAY_SPEED_IN_KNOTS  0x000000010 
     104 
     105 
     106static float course = 0.f;  //degrees 
     107static float altitude = 0.f; 
     108static float speed = 0.f; //Speed over ground in KNOTS!! 
     109static int satellites = 0;  //Number of satellites in use (00-12) 
     110static int quality = 0;   //GPS quality indicator (0 - fix not valid, 1 - GPS fix, 2 - DGPS fix)  
     111static char gpsStatus = 'V';  //A=active or V=Void  
     112static unsigned long gpsTime = 0; //UTC of position fix in hhmmss format  
     113static unsigned long gpsDate = 0; //Date in ddmmyy format 
     114 
     115static int msgCounter = 0;  //debug counter 
    73116/* ---------------------------------------------------------------------------------------*/ 
    74117/* STEP 1 : allocate the data structures. be careful if you put them on the stack because */ 
    75118/*          they need to be live for the duration of the parser                           */ 
    76119/* ---------------------------------------------------------------------------------------*/ 
    77  
    78120static nmeap_context_t nmea;  /* parser context */ 
    79121static nmeap_gga_t gga;   /* this is where the data from GGA messages will show up */ 
    80122static nmeap_rmc_t rmc;   /* this is where the data from RMC messages will show up */ 
    81123static int user_data;   /* user can pass in anything. typically it will be a pointer to some user data */ 
    82 static int fd; 
    83  
     124 
     125static int fd_g;    /* port handler */ 
     126 
     127 
     128#ifdef EMULATE 
     129char test_vector[] = { 
     130    "$GPGGA,123519,3929.946667,N,11946.086667,E,1,08,0.9,545.4,M,46.9,M,,*4A\r\n" /* good */ 
     131  "$xyz,1234,asdfadfasdfasdfljsadfkjasdfk\r\n"  /* junk */ 
     132  "$GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68\r\n"  /* good */ 
     133  "$GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*48\r\n"  /* checksum error */ 
     134}; 
     135#endif 
    84136 
    85137 
    86138/************************************************************************* 
    87  * LINUX IO 
    88  */ 
    89139 
    90140/* 
     
    93143 */ 
    94144 
     145#ifndef EMULATE 
    95146static int openPort(const char *tty, int baud) 
    96147{ 
     
    135186    return fd; 
    136187} 
    137  
    138  
    139  
    140 static void printGps(nmeap_gga_t * gga, nmeap_rmc_t * rmc) 
    141 { 
    142     float myCourse = rmc->course; /* I assume 0 degree = North */ 
    143  
    144     char courses[8][3] = { "N ", "NO", "O ", "SO", "S ", "SW", "W ", "NW" }; 
    145     float degrees[8] = { 22.5f, 67.5f, 112.5f, 157.5f, 202.5f, 247.5f, 292.5f, 337.5f }; 
    146     int selectedDegree = 0; 
    147     int n; 
    148  
    149     for (n = 0; n < 8; n++) { 
    150   if (myCourse < degrees[n]) { 
    151       selectedDegree = n; 
    152       break; 
    153   } 
    154     } 
    155  
    156     debug("alt:%.0f speed:%.0f course:%s sat:%d quali:%d, warn:%c\n", gga->altitude, rmc->speed * 1.852f, /* knots -> km/h */ 
    157     courses[selectedDegree], gga->satellites, gga->quality, rmc->warn /* A=active or V=Void */ 
    158   ); 
    159  
    160 } 
    161  
    162  
    163 /* 
    164 #define SHOW_ALTITUDE   0x0000001 
    165 #define SHOW_SPEED  0x0000010 
    166 #define SHOW_COURSE   0x0000100 
    167 #define SHOW_SATELLITES 0x0001000 
    168 #define SHOW_QUALITY  0x0010000 
    169 #define SHOW_WARN   0x0100000 
    170 */ 
    171  
    172 static void parse(RESULT * result, RESULT * theOptions) 
    173 { 
    174     char *value = " "; 
    175     int finito = 0; 
     188#endif 
     189 
     190/** called when a gpgga message is received and parsed */ 
     191static void gpgga_callout( __attribute__ ((unused)) nmeap_context_t * context, void *data, __attribute__ ((unused)) 
     192        void *user_data) 
     193{ 
     194    nmeap_gga_t *gga = (nmeap_gga_t *) data; 
     195 
     196    altitude = gga->altitude; 
     197    satellites = gga->satellites; 
     198    quality = gga->quality; 
     199    msgCounter++; 
     200} 
     201 
     202/** called when a gprmc message is received and parsed */ 
     203static void gprmc_callout( __attribute__ ((unused)) nmeap_context_t * context, void *data, __attribute__ ((unused)) 
     204        void *user_data) 
     205{ 
     206    nmeap_rmc_t *rmc = (nmeap_rmc_t *) data; 
     207 
     208    speed = rmc->speed; 
     209    gpsStatus = rmc->warn; 
     210    gpsTime = rmc->time; 
     211    gpsDate = rmc->date; 
     212    msgCounter++; 
     213} 
     214 
     215 
     216static int prepare_gps_parser() 
     217{ 
     218    int status; 
     219    char *port = "/dev/usb/tts/1"; 
     220    char *test; 
     221 
     222    if ((test = getenv("GPS_PORT"))) {  /* define your port via env variable */ 
     223  port = test; 
     224    } 
     225 
     226    /* --------------------------------------- */ 
     227    /* open the serial port device             */ 
     228    /* using default 4800 baud for most GPS    */ 
     229    /* --------------------------------------- */ 
     230#ifndef EMULATE 
     231    fd_g = openPort(port, B4800); 
     232    if (fd_g < 0) { 
     233  /* open failed */ 
     234  error("GPS PLUGIN, Error: openPort %d", fd_g); 
     235  return fd_g; 
     236    } 
     237#endif 
     238 
     239    /* --------------------------------------- */ 
     240    /*STEP 2 : initialize the nmea context    */ 
     241    /* --------------------------------------- */ 
     242    status = nmeap_init(&nmea, (void *) &user_data); 
     243    if (status != 0) { 
     244  error("GPS PLUGIN, Error: nmeap_init %d", status); 
     245  exit(1); 
     246    } 
     247 
     248    /* --------------------------------------- */ 
     249    /*STEP 3 : add standard GPGGA parser      */ 
     250    /* -------------------------------------- */ 
     251    status = nmeap_addParser(&nmea, "GPGGA", nmeap_gpgga, gpgga_callout, &gga); 
     252    if (status != 0) { 
     253  error("GPS PLUGIN, Error: nmeap_add GPGGA parser, error:%d", status); 
     254  return -1; 
     255    } 
     256 
     257    /* --------------------------------------- */ 
     258    /*STEP 4 : add standard GPRMC parser      */ 
     259    /* -------------------------------------- */ 
     260    /* status = nmeap_addParser(&nmea,"GPRMC",nmeap_gprmc,gprmc_callout,&rmc); */ 
     261    status = nmeap_addParser(&nmea, "GPRMC", nmeap_gprmc, gprmc_callout, &rmc); 
     262    if (status != 0) { 
     263  error("GPS PLUGIN, Error: nmeap_add GPRMC parser, error:%d", status); 
     264  return -1; 
     265    } 
     266 
     267    return fd_g; 
     268} 
     269 
     270 
     271 
     272static void parse(RESULT * result, RESULT * theOptions, RESULT * displayOptions) 
     273{ 
     274//    char *value = " "; 
     275//    int finito = 0; 
    176276 
    177277    int rem; 
     
    179279    int status; 
    180280    int len; 
    181     int lame; 
    182281    long options; 
    183     char buffer[32]; 
     282    long dispOptions; 
     283#ifndef EMULATE 
     284    char buffer[128]; 
     285#endif 
    184286 
    185287    options = R2N(theOptions); 
    186     if (options & SHOW_ALTITUDE) 
    187  
    188   while (finito == 0) { 
    189  
    190       /* ---------------------------------------- */ 
    191       /* STEP 6 : get a buffer of input          */ 
    192       /* --------------------------------------- */ 
    193       len = rem = read(fd, buffer, sizeof(buffer)); 
    194       if (len <= 0) { 
    195     error("GPS Plugin, Error read from port"); 
     288    dispOptions = R2N(displayOptions); 
     289    //error("options: %x\n",options); 
     290 
     291    /* ---------------------------------------- */ 
     292    /* STEP 6 : get a buffer of input          */ 
     293    /* --------------------------------------- */ 
     294#ifdef EMULATE 
     295    len = rem = sizeof(test_vector); 
     296#else 
     297    len = rem = read(fd_g, buffer, sizeof(buffer)); 
     298 
     299    /* --------------------------------------- */ 
     300    /*STEP 7 : pass it to the parser           */ 
     301    /* status indicates whether a complete msg */ 
     302    /* arrived for this byte                   */ 
     303    /* NOTE : in addition to the return status */ 
     304    /* the message callout will be fired when  */ 
     305    /* a complete message is processed         */ 
     306    /* --------------------------------------- */ 
     307    if (len <= 0) { 
     308  error("GPS Plugin, Error read from port, try using the GPS_PORT env variable (export GPS_PORT=/dev/mydev)"); 
     309  //break; 
     310    } 
     311#endif 
     312 
     313    /* ---------------------------------------------- */ 
     314    /* STEP 7 : process input until buffer is used up */ 
     315    /* ---------------------------------------------- */ 
     316    offset = 0; 
     317    while (rem > 0) { 
     318#ifdef EMULATE 
     319  status = nmeap_parseBuffer(&nmea, &test_vector[offset], &rem); 
     320#else 
     321  status = nmeap_parseBuffer(&nmea, &buffer[offset], &rem); 
     322//      error("loop, remaining=%d, read bytes=%d\n",rem,offset);         
     323#endif 
     324  offset += (len - rem); 
     325    } 
     326 
     327    /* --------------------------------------- */ 
     328    /* DISPLAY stuff comes here...             */ 
     329    /* --------------------------------------- */ 
     330    char *value = " "; 
     331    char outputStr[80]; 
     332    memset(outputStr, 0, 80); 
     333 
     334    if (options & SHOW_ALTITUDE) { 
     335  if (dispOptions & DISPLAY_NO_PREFIX) 
     336      sprintf(outputStr, "%s%.0f ", outputStr, altitude); 
     337  else 
     338      sprintf(outputStr, "%salt:%.0f ", outputStr, altitude); 
     339    } 
     340    if (options & SHOW_SPEED) { 
     341  float knotsConvert = 1.852f;  //default speed display=km/h 
     342  if (dispOptions & DISPLAY_SPEED_IN_KNOTS) 
     343      knotsConvert = 1.0f;  //use knots 
     344 
     345  if (dispOptions & DISPLAY_NO_PREFIX) 
     346      sprintf(outputStr, "%s%.0f ", outputStr, speed * knotsConvert); 
     347  else 
     348      sprintf(outputStr, "%sspd:%.0f ", outputStr, speed * knotsConvert); 
     349    } 
     350    if (options & SHOW_COURSE) { 
     351  char courses[8][3] = { "N ", "NO", "O ", "SO", "S ", "SW", "W ", "NW" }; 
     352  float degrees[8] = { 22.5f, 67.5f, 112.5f, 157.5f, 202.5f, 247.5f, 292.5f, 337.5f }; 
     353  int selectedDegree = 0; 
     354  int n; 
     355 
     356  for (n = 0; n < 8; n++) { 
     357      if (course < degrees[n]) { 
     358    selectedDegree = n; 
    196359    break; 
    197360      } 
    198  
    199       /* ---------------------------------------------- */ 
    200       /* STEP 7 : process input until buffer is used up */ 
    201       /* ---------------------------------------------- */ 
    202  
    203       offset = 0; 
    204       lame = 0; 
    205  
    206       while (rem > 0) { 
    207     status = nmeap_parseBuffer(&nmea, &buffer[offset], &rem); 
    208     offset += (len - rem); 
    209  
    210     switch (status) { 
    211     case NMEAP_GPGGA: 
    212         /* GOT A GPGGA MESSAGE */ 
    213         lame++; 
    214         break; 
    215     case NMEAP_GPRMC: 
    216         /* GOT A GPRMC MESSAGE */ 
    217         lame++; 
    218         break; 
    219     default: 
    220         debug("unhandled status: %d", status); 
    221         break; 
    222     } 
    223     if (lame > 1) { 
    224         finito = 1; 
    225         printGps(&gga, &rmc); 
    226     } 
    227       } 
    228  
    229361  } 
    230  
    231  
    232     /* store result */ 
     362  if (dispOptions & DISPLAY_NO_PREFIX) 
     363      sprintf(outputStr, "%s%s ", outputStr, courses[selectedDegree]); 
     364  else 
     365      sprintf(outputStr, "%sdir:%s ", outputStr, courses[selectedDegree]); 
     366    } 
     367    if (options & SHOW_SATELLITES) { 
     368  if (dispOptions & DISPLAY_NO_PREFIX) 
     369      sprintf(outputStr, "%s%d ", outputStr, satellites); 
     370  else 
     371      sprintf(outputStr, "%ssat:%d ", outputStr, satellites); 
     372    } 
     373    if (options & SHOW_QUALITY) { 
     374  if (dispOptions & DISPLAY_NO_PREFIX) 
     375      sprintf(outputStr, "%s%d ", outputStr, quality); 
     376  else 
     377      sprintf(outputStr, "%squa:%d ", outputStr, quality); 
     378    } 
     379    if (options & SHOW_STATUS) { 
     380  if (dispOptions & DISPLAY_NO_PREFIX) 
     381      sprintf(outputStr, "%s%c ", outputStr, gpsStatus); 
     382  else 
     383      sprintf(outputStr, "%ssta:%c ", outputStr, gpsStatus); 
     384    } 
     385    if (options & SHOW_TIME_UTC) { 
     386  if (dispOptions & DISPLAY_NO_PREFIX) 
     387      sprintf(outputStr, "%s%ld ", outputStr, gpsTime); 
     388  else 
     389      sprintf(outputStr, "%sutc:%ld ", outputStr, gpsTime); 
     390    } 
     391    if (options & SHOW_DATE) { 
     392  if (dispOptions & DISPLAY_NO_PREFIX) 
     393      sprintf(outputStr, "%s%ld ", outputStr, gpsDate); 
     394  else 
     395      sprintf(outputStr, "%sdat:%ld ", outputStr, gpsDate); 
     396    } 
     397 
     398    value = strdup(outputStr); 
    233399    SetResult(&result, R_STRING, value); 
    234  
    235400    free(value); 
    236401} 
    237  
    238402 
    239403 
     
    242406int plugin_init_gps(void) 
    243407{ 
    244     int fd; 
    245     int status; 
    246     char *port = "/dev/usb/tty/1"; 
    247     char *test; 
    248  
    249     if ((test = getenv("GPS_PORT"))) {  /* define your port via env variable */ 
    250   port = test; 
    251     } 
    252  
    253  
    254     /* --------------------------------------- */ 
    255     /* open the serial port device             */ 
    256     /* using default 4800 baud for most GPS    */ 
    257     /* --------------------------------------- */ 
    258     fd = openPort(port, B4800); 
    259     if (fd < 0) { 
    260   /* open failed */ 
    261   error("GPS PLUGIN, Error: openPort %d", fd); 
    262   return fd; 
    263     } 
    264  
    265     /* --------------------------------------- */ 
    266     /*STEP 2 : initialize the nmea context    */ 
    267     /* --------------------------------------- */ 
    268     status = nmeap_init(&nmea, (void *) &user_data); 
    269     if (status != 0) { 
    270   error("GPS PLUGIN, Error: nmeap_init %d", status); 
    271   exit(1); 
    272     } 
    273  
    274     /* --------------------------------------- */ 
    275     /*STEP 3 : add standard GPGGA parser      */ 
    276     /* -------------------------------------- */ 
    277     status = nmeap_addParser(&nmea, "GPGGA", nmeap_gpgga, 0, &gga); 
    278     if (status != 0) { 
    279   error("GPS PLUGIN, Error: nmeap_add GPGGA parser, error:%d", status); 
    280   return -1; 
    281     } 
    282  
    283     /* --------------------------------------- */ 
    284     /*STEP 4 : add standard GPRMC parser      */ 
    285     /* -------------------------------------- */ 
    286     /* status = nmeap_addParser(&nmea,"GPRMC",nmeap_gprmc,gprmc_callout,&rmc); */ 
    287     status = nmeap_addParser(&nmea, "GPRMC", nmeap_gprmc, 0, &rmc); 
    288     if (status != 0) { 
    289   error("GPS PLUGIN, Error: nmeap_add GPRMC parser, error:%d", status); 
    290   return -1; 
    291     } 
    292  
     408    printf("PLUGIN INIT\n"); 
     409    prepare_gps_parser(); 
    293410 
    294411    /* register all our cool functions */ 
    295412    /* the second parameter is the number of arguments */ 
    296413    /* -1 stands for variable argument list */ 
    297     AddFunction("gps::parse", 0, parse); 
     414    AddFunction("gps::parse", 2, parse); 
    298415 
    299416    return 0; 
     
    302419void plugin_exit_gps(void) 
    303420{ 
    304     /* close the serial port */ 
    305     close(fd); 
    306  
    307 } 
     421#ifndef EMULATE 
     422    close(fd_g); 
     423#endif 
     424}