// 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;
}
Exemple #2
0
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;
}