Example #1
0
/**
 * Parses a message. If the message could not be parsed, NULL is returned. The
 * return value be cast to the proper struct, based on the determined message
 * type.
 *
 * If the message could not be parsed, and if the outError pointer is non-NULL,
 * its contents will be set to the appropriate error code.
 */
LIBNMEA_PUBLIC nmea_message_t *nmea_parse_message(char *message, nmea_error_t *outError) {
    assert(message != NULL);

    // If we can parse the message, point to it here
    nmea_message_t *parsed;

    // Create a copy of the input message.
    int len = strlen(message);
    char *copy = malloc(len + 2);
    strncpy(copy, message, len + 2);

    // Figure out what function will parse this message
    nmea_message_type_t t = nmea_get_message_type(message);

    switch(t) {
    case kNMEAMessageGGA:
        parsed = (nmea_message_t *) parse_gga(copy, outError);
        break;

    case kNMEAMessageGSA:
        parsed = (nmea_message_t *) parse_gsa(copy, outError);
        break;

    case kNMEAMessageGSV:
        parsed = (nmea_message_t *) parse_gsv(copy, outError);
        break;

    case kNMEAMessageVTG:
        parsed = (nmea_message_t *) parse_vtg(copy, outError);
        break;

    // The message was of an unknown type. (Handles kNMEAMessageUnknown)
    default:
        if(outError) *outError = kNMEAErrorTypeNotUnderstood;
        parsed = NULL;
        break;
    }

    // Ensure we don't pass back invalid data.
    assert(parsed);

    // Clean up
    free(copy);

    parsed->type = t;

    // We're done.
    return parsed;
}
Example #2
0
int main(int argc, char* argv[])
{
    FILE* file;
    int arg_index;
    char* buf = 0;
    const unsigned int bufsize = 256;
    const char* tokens[32];
    const int len = sizeof tokens / sizeof tokens[0];
    int token_count;
    struct GGA* gga;
    struct GNS* gns;
    struct GSA* gsa;
    struct RMC* rmc;

    buf = malloc(bufsize);
    if (!buf) {
        goto exit;
    }

    for (arg_index=1; arg_index<argc; ++arg_index) {
        file = fopen(argv[arg_index], "r");
        if (!file) {
            continue;
        }

        while (fgets(buf, bufsize, file)) {
            if (strlen(buf) < 10) continue;

            if (!verify_checksum(buf)) break;


            fprintf(stdout, "%s", buf);

            token_count =  tokenize(buf, tokens, len);

            if (0 !=(gga = parse_gga(tokens, token_count))) {
                fprintf(stdout, "   GGA %02d:%02d:%02d %.6f , %.6f %d, %d, %.2f, %.1f(%s), %.1f(%s) \n",
                        gga->hour, gga->min, gga->sec, gga->lat, gga->lon, gga->quality, gga->sat_count, gga->hdop, gga->altitude, tokens[10], gga->geoid_height, tokens[12]);

                free(gga);
            }
            else if (0 != (gns = parse_gns(tokens, token_count))) {
                fprintf(stdout, "   GNS %02d:%02d:%02d %.6f , %.6f %s, %d, %.2f, %.1f(%s), %.1f(%s) \n",
                        gns->hour, gns->min, gns->sec, gns->lat, gns->lon, gns->mode, gns->sat_count, gns->hdop, gns->altitude, "m", gns->geoid_height, "m");

                free(gns);
            }
            else if (0 != (gsa = parse_gsa(tokens, token_count))) {
                int i;
                int prn;

                fprintf(stdout, "   GSA %c, %d, ", gsa->mode, gsa->fix_type);
                i = 0;
                while (i<12 && 0 != (prn = gsa->prn[i])) {
                    fprintf(stdout,"%d, ", prn);
                    ++i;
                }
                fprintf(stdout, "%.1f, %.1f, %.1f\n", gsa->pdop, gsa->hdop, gsa->vdop);

                free(gsa);
            }
            else if (0 != (rmc = parse_rmc(tokens, token_count))) {
                    fprintf(stdout, "   RMC %02d:%02d:%02d  %.6f , %.6f  %.1f(knots), %.1f(degrees) %02d-%02d-%02d\n",
                            rmc->hour, rmc->min, rmc->sec, rmc->lat, rmc->lon, rmc->speed, rmc->heading, rmc->day, rmc->month, rmc->year);

                    free(rmc);
            } 
        } // while

        fclose(file);
    }

exit: 
    if (buf) {
        free(buf);
    }
    return 0;
}
Example #3
0
bool put_nmea_msg(struct nmea_parser_t *ctx, const uint8_t *msg, size_t msg_size, struct gps_msg_status_t *status)
{
  unsigned i;
  char msg_id[9];

  assert(msg_size > 1 &&  msg_size <= NMEA_MAX);
  assert((size_t)looks_like_nmea(msg, msg_size) == msg_size);

  status->is_valid = false;
  status->location_changed = false;
  status->err[0] = '\0';

  ctx->stats->rcvd.nmea.last_msg_ts = ctx->stats->rcvd.last_byte_ts;
  ctx->stats->rcvd.nmea.total += 1;

  for (i=0; i < sizeof(msg_id); ++i) {
    if (i >= msg_size) {
      msg_id[i] = '\0';
      break;
    }else {
      if (msg[i] == ',') {
        msg_id[i] = '\0';
        break;
      }else {
        msg_id[i] = (char)msg[i];
      }
    }
  }
  msg_id[sizeof(msg_id)-1] = '\0';

  if (
      (strcmp("$GPGGA", msg_id) == 0)
      || (strcmp("$GNGGA", msg_id) == 0)
      || (strcmp("$GLGGA", msg_id) == 0)
      || (strcmp("$GAGGA", msg_id) == 0)
      ) {
    struct nmea_gpgga_t gxgga;
    if (parse_gga(msg, msg_size, &gxgga, status)) {
      if (!is_same_fix_time(ctx->fix.fix_time, gxgga.fix_time)) {
        close_nmea_fix(ctx, status);
        open_nmea_fix(&ctx->fix, gxgga.fix_time);
      }
      ctx->fix.gpgga_active = true;
      ctx->fix.gpgga = gxgga;
      ctx->stats->rcvd.nmea.gga += 1;
    }
  }else if (
      (strcmp("$GPRMC", msg_id) == 0)
      || (strcmp("$GNRMC", msg_id) == 0)
      || (strcmp("$GLRMC", msg_id) == 0)
      || (strcmp("$GARMC", msg_id) == 0)
      ) {
    struct nmea_gprmc_t gxrmc;
    if (parse_rmc(msg, msg_size, &gxrmc, status)) {
      if (!is_same_fix_time(ctx->fix.fix_time, gxrmc.fix_time)) {
        close_nmea_fix(ctx, status);
        open_nmea_fix(&ctx->fix, gxrmc.fix_time);
      }
      ctx->fix.gprmc_active = true;
      ctx->fix.gprmc = gxrmc;
      ctx->stats->rcvd.nmea.rmc += 1;
    }
  }else if (strcmp("$GPGLL", msg_id) == 0) {
    struct nmea_gpgll_t gxgll;
    if (parse_gll(msg, msg_size, &gxgll, status)) {
      if (!is_same_fix_time(ctx->fix.fix_time, gxgll.fix_time)) {
        close_nmea_fix(ctx, status);
        open_nmea_fix(&ctx->fix, gxgll.fix_time);
      }
      ctx->fix.gpgll_active = true;
      ctx->fix.gpgll = gxgll;
      ctx->stats->rcvd.nmea.gll += 1;
    }
  }else if (strcmp("$GPGST", msg_id) == 0) {
    struct nmea_gpgst_t gpgst;
    if (parse_gst(msg, msg_size, &gpgst, status)) {
      if (!is_same_fix_time(ctx->fix.fix_time, gpgst.fix_time)) {
        close_nmea_fix(ctx, status);
        open_nmea_fix(&ctx->fix, gpgst.fix_time);
      }
      ctx->fix.gpgst_active = true;
      ctx->fix.gpgst = gpgst;
      ctx->stats->rcvd.nmea.gst += 1;
    }
  }else if (strcmp("$GPGSA", msg_id) == 0) {
    struct nmea_gpgsa_t gpgsa;
    if (parse_gsa(msg, msg_size, &gpgsa, status)) {
      gpgsa.is_valid = true;
      ctx->gpgsa = gpgsa;
      ctx->stats->rcvd.nmea.gsa += 1;
    }
  }else if (strcmp("$GPVTG", msg_id) == 0) {
    struct nmea_gpvtg_t gpvtg;
    if (parse_vtg(msg, msg_size, &gpvtg, status)) {
      gpvtg.is_valid = true;
      ctx->gpvtg = gpvtg;
      ctx->stats->rcvd.nmea.vtg += 1;
    }
  }else if (strcmp("$GPZDA", msg_id) == 0) {
    struct nmea_gpzda_t gpzda;
    if (parse_zda(msg, msg_size, &gpzda, status)) {
      ctx->fix.gpzda_active = true;
      ctx->fix.gpzda = gpzda;
      ctx->stats->rcvd.nmea.zda += 1;
    }
  }else if (strcmp("$GPGSV", msg_id) == 0) {
    // TODO
    status->is_valid = true;
    ctx->stats->rcvd.nmea.gsv += 1;
  }else if (strcmp("$PUBX", msg_id) == 0) {
    // TODO
    status->is_valid = true;
    ctx->stats->rcvd.nmea.pubx += 1;
  } else {
    set_nmea_error(status, msg, msg_size, "unk msg");
    status->is_valid = true;
    ctx->stats->rcvd.nmea.other += 1;
  }

  return status->is_valid;
}