// Processes a just-completed term // Returns true if new sentence has just passed checksum test and is validated bool AP_GPS_NMEA::_term_complete() { // handle the last term in a message if (_is_checksum_term) { uint8_t checksum = 16 * _from_hex(_term[0]) + _from_hex(_term[1]); if (checksum == _parity) { if (_gps_data_good) { switch (_sentence_type) { case _GPS_SENTENCE_GPRMC: time = _new_time; date = _new_date; latitude = _new_latitude * 10; // degrees*10e5 -> 10e7 longitude = _new_longitude * 10; // degrees*10e5 -> 10e7 ground_speed = _new_speed; ground_course = _new_course; fix = true; break; case _GPS_SENTENCE_GPGGA: altitude = _new_altitude; time = _new_time; latitude = _new_latitude * 10; // degrees*10e5 -> 10e7 longitude = _new_longitude * 10; // degrees*10e5 -> 10e7 num_sats = _new_satellite_count; hdop = _new_hdop; fix = true; break; case _GPS_SENTENCE_GPVTG: ground_speed = _new_speed; ground_course = _new_course; // VTG has no fix indicator, can't change fix status break; } } else { switch (_sentence_type) { case _GPS_SENTENCE_GPRMC: case _GPS_SENTENCE_GPGGA: // Only these sentences give us information about // fix status. fix = false; } } // we got a good message return true; } // we got a bad message, ignore it return false; } // the first term determines the sentence type if (_term_number == 0) { if (!strcmp_P(_term, _gprmc_string)) { _sentence_type = _GPS_SENTENCE_GPRMC; } else if (!strcmp_P(_term, _gpgga_string)) { _sentence_type = _GPS_SENTENCE_GPGGA; } else if (!strcmp_P(_term, _gpvtg_string)) { _sentence_type = _GPS_SENTENCE_GPVTG; // VTG may not contain a data qualifier, presume the solution is good // unless it tells us otherwise. _gps_data_good = true; } else { _sentence_type = _GPS_SENTENCE_OTHER; } return false; } // 32 = RMC, 64 = GGA, 96 = VTG if (_sentence_type != _GPS_SENTENCE_OTHER && _term[0]) { switch (_sentence_type + _term_number) { // operational status // case _GPS_SENTENCE_GPRMC + 2: // validity (RMC) _gps_data_good = _term[0] == 'A'; break; case _GPS_SENTENCE_GPGGA + 6: // Fix data (GGA) _gps_data_good = _term[0] > '0'; break; case _GPS_SENTENCE_GPVTG + 9: // validity (VTG) (we may not see this field) _gps_data_good = _term[0] != 'N'; break; case _GPS_SENTENCE_GPGGA + 7: // satellite count (GGA) _new_satellite_count = atol(_term); break; case _GPS_SENTENCE_GPGGA + 8: // HDOP (GGA) _new_hdop = _parse_decimal(); break; // time and date // case _GPS_SENTENCE_GPRMC + 1: // Time (RMC) case _GPS_SENTENCE_GPGGA + 1: // Time (GGA) _new_time = _parse_decimal(); break; case _GPS_SENTENCE_GPRMC + 9: // Date (GPRMC) _new_date = atol(_term); break; // location // case _GPS_SENTENCE_GPRMC + 3: // Latitude case _GPS_SENTENCE_GPGGA + 2: _new_latitude = _parse_degrees(); break; case _GPS_SENTENCE_GPRMC + 4: // N/S case _GPS_SENTENCE_GPGGA + 3: if (_term[0] == 'S') _new_latitude = -_new_latitude; break; case _GPS_SENTENCE_GPRMC + 5: // Longitude case _GPS_SENTENCE_GPGGA + 4: _new_longitude = _parse_degrees(); break; case _GPS_SENTENCE_GPRMC + 6: // E/W case _GPS_SENTENCE_GPGGA + 5: if (_term[0] == 'W') _new_longitude = -_new_longitude; break; case _GPS_SENTENCE_GPGGA + 9: // Altitude (GPGGA) _new_altitude = _parse_decimal(); break; // course and speed // case _GPS_SENTENCE_GPRMC + 7: // Speed (GPRMC) case _GPS_SENTENCE_GPVTG + 5: // Speed (VTG) _new_speed = (_parse_decimal() * 514) / 1000; // knots-> m/sec, approximiates * 0.514 break; case _GPS_SENTENCE_GPRMC + 8: // Course (GPRMC) case _GPS_SENTENCE_GPVTG + 1: // Course (VTG) _new_course = _parse_decimal(); break; } } return false; }
int parse_json_file(FILE *fptr, JSON_T *json_obj) { int ret; char *key; char first_meet; char *tmpstr; long long tmpnum; double floatnum, decimal; JSON_T *value; if (!json_obj) return -ENOMEM; key = NULL; tmpstr = NULL; value = NULL; memset(json_obj, 0, sizeof(JSON_T)); json_obj->type = JSON; json_obj->keys = NULL; _PARSE_SYMBOL(fptr, "{", NULL); while (!feof(fptr)) { _PARSE_SYMBOL(fptr, "\"}", &first_meet); if (first_meet == '}') break; ret = _parse_string(fptr, &key); if (ret < 0) goto error_handle; //printf("string = %s : ", key); _PARSE_SYMBOL(fptr, ":", NULL); _PARSE_SYMBOL(fptr, "\"{-0123456789.", &first_meet); value = malloc(sizeof(JSON_T)); if (!value) { ret = -ENOMEM; goto error_handle; } memset(value, 0, sizeof(JSON_T)); switch (first_meet) { case '\"': ret = _parse_string(fptr, &tmpstr); if (ret < 0) goto error_handle; value->type = STRING; value->str = tmpstr; //printf("value = %s\n", tmpstr); break; case '{': fseek(fptr, -1, SEEK_CUR); ret = parse_json_file(fptr, value); if (ret < 0) goto error_handle; break; case '-': ret = _parse_integer(fptr, &tmpnum); if (ret < 0) { goto error_handle; } else if (ret == 1) { ret = _parse_decimal(fptr, &decimal); if (ret < 0) goto error_handle; floatnum = tmpnum + decimal; value->type = FLOAT; value->floating = -floatnum; } else { value->type = INTEGER; value->integer = -tmpnum; } //printf("value = %lld\n", -tmpnum); break; default: fseek(fptr, -1, SEEK_CUR); ret = _parse_integer(fptr, &tmpnum); if (ret < 0) { goto error_handle; } else if (ret == 1) { ret = _parse_decimal(fptr, &decimal); if (ret < 0) goto error_handle; floatnum = tmpnum + decimal; value->type = FLOAT; value->floating = floatnum; } else { value->type = INTEGER; value->integer = tmpnum; } //printf("value = %lld\n", tmpnum); break; } /* Insert */ ret = insert_json_obj(json_obj, key, value); if (ret < 0) goto error_handle; key = NULL; tmpstr = NULL; value = NULL; _PARSE_SYMBOL(fptr, "},", &first_meet); if (first_meet == '}') break; } return 0; error_handle: /* Do not free self because it perhaps results in double free error when recursing */ free_json_obj_field(json_obj); if (key) free(key); if (tmpstr) free(tmpstr); if (value) free(value); return ret; }