Changeset 842

Show
Ignore:
Timestamp:
09/15/07 08:10:48 (14 months ago)
Author:
michael
Message:

GPS plugin V0.3 by michu

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/plugin_gps.c

    r841 r842  
    4040 *       -added support for gps device with 9600 baud (env. variable) 
    4141 *       -added the option that the widget graps data from the buffer and not from the gps device (usefull for multible widgets) 
     42 *      v0.3 -improved nmea parsing 
     43 *           -improved gps-emulator 
     44 *           -time is now updated with rmc and gga sentence 
    4245 * 
    4346 * TODO: 
     
    7174 *              each widget will get updates and cause some ugly side effects, specially when you display the time 
    7275 *              by enabling this option, the widget will not read any nmea data from the serial port. 
    73  *              KEEP IN MIND that there must be ONE widget which does NOT get buffered data (means read data from the port) 
     76 *              KEEP IN MIND that there must be ONE widget which get buffered data (means read data from the port) 
     77 * 
     78 *      #define SHOW_NMEA_STATUS        0x010000000 OK:0033/Error:0002/Incomplete:0002 
     79 * 
    7480 * 
    7581 *  Examples:   
     
    109115 
    110116#define EMULATE     //remove comment to enable gps data emulation... 
    111 #define EMU_BUFFER_READ_SIZE 32 //how many bytes are read each loop aka emulation speed 
     117#define EMU_BUFFER_READ_SIZE 128  //how many bytes are read each loop aka emulation speed 
     118#define BUFFER_SIZE 256 
    112119 
    113120#define SHOW_ALTITUDE     0x000000001 
     
    128135            //KEEP IN MIND that there must be ONE widget which does not get buffered data (means read data from the port) 
    129136#define OPTION_DEBUG    0x000010000 
    130  
     137#define SHOW_NMEA_STATUS  0x010000000 
    131138 
    132139static float course = 0.f;  //degrees 
     
    139146static unsigned long gpsDate = 0; //Date in ddmmyy format 
    140147 
    141 static int msgCounter = 0;  //debug counter 
     148static int msgCounter = 0;  //parsed nmea-sentence 
     149static int errCounter = 0;  //parsed error nmea-sentence 
     150static int incomplCounter = 0;  //incomplete parsed nmea-sentence 
    142151/* ---------------------------------------------------------------------------------------*/ 
    143152/* STEP 1 : allocate the data structures. be careful if you put them on the stack because */ 
     
    154163 
    155164static char Name[] = "plugin_gps.c"; 
     165 
     166static int fndStr = 0;    //how many bytes were saved from the last read 
     167static char backBuffer[BUFFER_SIZE];  //the buffer to save incomplete nmea strings 
     168 
    156169 
    157170#ifdef EMULATE 
     
    177190  "$GPRMC,165117.000,A,5601.0318,N,01211.3505,E,0.08,45.32,190706,,*3F\r\n" 
    178191  "$GPGGA,165118.000,5601.0318,N,01211.3505,E,1,07,1.2,23.0,M,41.6,M,,0000*68\r\n" 
    179   "$GPRMC,165118.000,A,5601.0318,N,01211.3505,E,0.10,37.49,190706,,*30\r\n" 
    180   "$GPGGA,165119.000,5601.0318,N,01211.3504,E,1,06,1.2,23.0,M,41.6,M,,0000*69\r\n" 
     192  "$GPRMC,165118.000,A,5601.0318,N,01211.3505,E,0.10,37.49,190706,,*30\r\n"*/ 
     193    "$GPGGA,165119.000,5601.0318,N,01211.3504,E,1,06,1.2,23.0,M,41.6,M,,0000*69\r\n" 
    181194  "$GPRMC,165119.000,A,5601.0318,N,01211.3504,E,0.08,27.23,190706,,*34\r\n" 
    182195  "$GPGGA,165120.000,5601.0318,N,01211.3504,E,1,07,1.2,23.0,M,41.6,M,,0000*62\r\n" 
     
    211224  "$GPRMC,094059.000,A,5409.998934,N,00859.370505,E,0.576,0.00,301206,,,A*53\r\n" 
    212225  "$GPGGA,094100.000,5409.999097,N,00859.370542,E,1,12,0.82,-5.177,M,45.414,M,,*4C\r\n" 
    213   "$GPRMC,094100.000,A,5409.999097,N,00859.370542,E,0.705,0.00,301206,,,A\r\n" */ 
     226  "$GPRMC,094100.000,A,5409.999097,N,00859.370542,E,0.705,0.00,301206,,,A\r\n" 
    214227  "$GPGGA,004037.851,0000.0000,N,00000.0000,E,0,00,50.0,0.0,M,0.0,M,0.0,0000*7A\r\n" 
    215228  "$GPGGA,175218.255,4657.3391,N,00726.2666,E,1,04,9.0,568.6,M,48.0,M,0.0,0000*7B\r\n" 
     
    342355    satellites = gga->satellites; 
    343356    quality = gga->quality; 
    344     msgCounter++; 
    345      
    346     if (debug==1) 
    347         debug("gps:debug: get gga callout, msg nr: %d\n",msgCounter); 
    348      
    349 } 
     357    gpsTime = gga->time; 
     358 
     359    if (debug == 1) 
     360  debug("gps:debug: get gga callout\n"); 
     361 
     362} 
     363 
     364 
     365//search a buffer for a string (forwards) 
     366int strLastOcc(char *theBuffer, char searchChar, int size) 
     367{ 
     368    int i, ret; 
     369 
     370    ret = -1; 
     371    for (i = size; i >= 0; i--) { 
     372  if (theBuffer[i] == searchChar) { 
     373      ret = i; 
     374      break; 
     375  } 
     376    } 
     377    return ret; 
     378} 
     379 
     380//search a buffer for a string (backwards)   
     381int strFirstOcc(char *theBuffer, char searchChar, int size) 
     382{ 
     383    int i, ret; 
     384    ret = -1; 
     385    for (i = 0; i < size; i++) { 
     386  if (theBuffer[i] == searchChar) { 
     387      ret = i; 
     388      break; 
     389  } 
     390    } 
     391    return ret; 
     392} 
     393 
     394 
    350395 
    351396/** called when a gprmc message is received and parsed */ 
     
    359404    gpsTime = rmc->time; 
    360405    gpsDate = rmc->date; 
    361     msgCounter++; 
    362      
    363     if (debug==1) 
    364         debug("gps:debug: get rmc callout, msg nr: %d\n",msgCounter); 
    365      
     406 
     407    if (debug == 1) 
     408  debug("gps:debug: get rmc callout\n"); 
     409 
    366410} 
    367411 
     
    441485    long options; 
    442486    long dispOptions; 
    443 #define BUFFER_SIZE 128     
     487 
    444488    char buffer[BUFFER_SIZE]; 
     489    char bufferTmp[BUFFER_SIZE]; 
     490 
     491    int validStart, validEnd; 
    445492 
    446493    options = R2N(theOptions); 
    447494    dispOptions = R2N(displayOptions); 
    448495    //error("options: %x\n",options); 
    449      
     496 
    450497    if (dispOptions & OPTION_DEBUG) 
    451   debug=1;       
    452      
     498  debug = 1; 
     499 
    453500    if ((dispOptions & OPTION_GET_BUFFERDATA) == 0) { 
    454501 
     
    456503  /* STEP 6 : get a buffer of input          */ 
    457504  /* --------------------------------------- */ 
     505 
     506  memset(buffer, 0, BUFFER_SIZE); 
     507  if (fndStr > BUFFER_SIZE) 
     508      fndStr = 0; 
     509  //copy unfinished nmea strings back 
     510  if (fndStr > 0) { 
     511      memcpy(buffer, backBuffer, fndStr); 
     512  } 
    458513#ifdef EMULATE 
     514  memcpy(&buffer[fndStr], &test_vector[emu_read_ofs], BUFFER_SIZE - fndStr); 
     515 
    459516  len = rem = EMU_BUFFER_READ_SIZE; 
    460517  emu_read_ofs += EMU_BUFFER_READ_SIZE; 
    461   if (emu_read_ofs > (sizeof(test_vector)-BUFFER_SIZE)) 
     518  if (emu_read_ofs > (sizeof(test_vector) - BUFFER_SIZE)) { 
    462519      emu_read_ofs = 0; 
    463   memcpy(buffer, &test_vector[emu_read_ofs], BUFFER_SIZE); 
     520      memset(buffer, 0, BUFFER_SIZE); 
     521  } 
    464522#else 
    465   memset(buffer, 0, sizeof(buffer)); 
    466   len = rem = read(fd_g, buffer, sizeof(buffer)); 
     523 
     524  len = rem = read(fd_g, buffer, BUFFER_SIZE - fndStr); 
    467525  if (len <= 0) { 
    468526      error("GPS Plugin, Error read from port, try using the GPS_PORT env variable (export GPS_PORT=/dev/mydev)"); 
    469527      //break; 
    470528  } 
    471   if (debug==1) 
    472       debug("gps:debug: read %d bytes\n",len); 
    473    
     529  if (debug == 1) 
     530      debug("gps:debug: read %d bytes\n", len); 
     531 
    474532#endif 
    475533  if (dispOptions & OPTION_RAW_NMEA) 
     
    479537  /* STEP 7 : process input until buffer is used up */ 
    480538  /* ---------------------------------------------- */ 
    481 //#ifdef EMULATE 
    482 //  offset = emu_read_ofs; 
    483 //#else 
     539  validStart = strFirstOcc(buffer, '$', len); 
     540  validEnd = strLastOcc(buffer, '\n', len); 
     541 
     542  if (validStart >= 0 && validEnd > 0 && validStart < validEnd) { 
     543      //valid string found 
     544      memcpy(bufferTmp, buffer, sizeof(buffer));  //save buffer 
     545      memset(backBuffer, 0, sizeof(backBuffer));  //clear backup buffer 
     546      memcpy(backBuffer, buffer + validEnd, len - validEnd);  // save incomplete nmea string 
     547      memset(buffer, 0, sizeof(buffer));  //clean buffer 
     548      memcpy(buffer, bufferTmp + validStart, validEnd - validStart + 1);  //copy valid name string 
     549      fndStr = len - validEnd + validStart; //save the size of the buffer 
     550  } else { 
     551      //no valid nmea string found 
     552      fndStr = 0; 
     553      memset(buffer, 0, sizeof(buffer)); 
     554      memset(backBuffer, 0, sizeof(backBuffer)); 
     555  } 
     556 
    484557  offset = 0; 
    485 //#endif 
    486  
    487   while (rem > 0) { 
    488 //#ifdef EMULATE 
    489 //      status = nmeap_parseBuffer(&nmea, &test_vector[offset], &rem); 
    490 //#else 
     558  if (debug == 1) 
     559      debug("backBuffer: %s\n", backBuffer); 
     560 
     561  //the nmeap_parseBuffer function needs whole nmea strings, combined string will NOT work! 
     562  validStart = strFirstOcc(buffer, '$', len); 
     563  validEnd = strFirstOcc(buffer, '\n', len); 
     564  while (validStart >= 0 && validEnd > 0 && validStart < validEnd) { 
     565      memset(bufferTmp, 0, sizeof(bufferTmp));  //empty temp buffer 
     566      memcpy(bufferTmp, buffer + offset + validStart, validEnd - validStart + 1); //fill temp buffer 
     567 
     568      if (debug == 1) 
     569    debug("submit: %s\n", bufferTmp); 
     570 
     571      rem = len - offset; 
     572      status = nmeap_parseBuffer(&nmea, (const char *) &bufferTmp, &rem); //parse it 
     573      if (status == -1) { 
     574    errCounter++; 
     575    error("parser error occured! (cnt: %i)\n", errCounter); 
     576      } else if (status == 0) { 
     577    incomplCounter++; 
     578      } else if (status > 0) 
     579    msgCounter++; 
     580 
     581      offset += validEnd - validStart + 1;  //update offset 
     582      validStart = strFirstOcc(buffer + offset, '$', len - offset); //find next sentence 
     583      validEnd = strFirstOcc(buffer + offset, '\n', len - offset); 
     584  } 
     585 
     586 
     587/*  while (rem > 0) { 
    491588      status = nmeap_parseBuffer(&nmea, &buffer[offset], &rem); 
    492589      debug("\nGPS::debug: remaining: %d bytes\n",rem); 
    493       //error("loop, remaining=%d, read bytes=%d\n",rem,offset);         
    494 //#endif 
    495590      offset += (len - rem); 
    496   } 
     591  }*/ 
    497592    }       // end of OPTION get bufferdata 
    498593 
     
    587682    } 
    588683 
    589     if (options == 0) {   //error, no parameter defined! 
     684 
     685    if (dispOptions & SHOW_NMEA_STATUS) { 
     686  if (dispOptions & OPTION_NO_PREFIX) 
     687      sprintf(outputStr, "%s%04d/%04d/%04d ", outputStr, msgCounter, errCounter, incomplCounter); 
     688  else 
     689      sprintf(outputStr, "%sOK:%03d/Er:%03d/In:%03d ", outputStr, msgCounter, errCounter, incomplCounter); 
     690    } 
     691 
     692    if (options == 0 && dispOptions == 0) { //error, no parameter defined! 
    590693  error("gps::parse() ERROR, no parameter specified!"); 
    591694  value = strdup("GPS ARG ERR");