static bool ReadLatitude(NMEAInputLine &line, Angle &value_r) { Angle value; if (!ReadPositiveAngle(line, value)) return false; if (line.read_first_char() == 'S') value = -value; value_r = value; return true; }
static bool ReadAltitude(NMEAInputLine &line, fixed &value_r) { fixed value; bool available = line.read_checked(value); char unit = line.read_first_char(); if (!available) return false; if (unit == _T('f') || unit == _T('F')) value = Units::ToSysUnit(value, unFeet); value_r = value; return true; }
bool NMEAParser::GLL(NMEAInputLine &line, NMEAInfo &info) { /* * $--GLL,llll.ll,a,yyyyy.yy,a,hhmmss.ss,a,m,*hh * * Field Number: * 1) Latitude * 2) N or S (North or South) * 3) Longitude * 4) E or W (East or West) * 5) Universal Time Coordinated (UTC) * 6) Status A - Data Valid, V - Data Invalid * 7) FAA mode indicator (NMEA 2.3 and later) * 8) Checksum */ GeoPoint location; bool valid_location = ReadGeoPoint(line, location); fixed this_time = TimeModify(line.read(fixed_zero), info.date_time_utc, info.date_available); this_time = TimeAdvanceTolerance(this_time); bool gps_valid = !NAVWarn(line.read_first_char()); if (!TimeHasAdvanced(this_time, info)) return true; if (!gps_valid) info.location_available.Clear(); else if (valid_location) info.location_available.Update(info.clock); if (valid_location) info.location = location; info.gps.real = real; #ifdef ANDROID info.gps.android_internal_gps = false; #endif return true; }
/** * Parses a RMC sentence * * $--RMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,xxxx,x.x,a,m,*hh * * Field Number: * 1) UTC Time * 2) Status, V=Navigation receiver warning A=Valid * 3) Latitude * 4) N or S * 5) Longitude * 6) E or W * 7) Speed over ground, knots * 8) Track made good, degrees true * 9) Date, ddmmyy * 10) Magnetic Variation, degrees * 11) E or W * 12) FAA mode indicator (NMEA 2.3 and later) * 13) Checksum * @param String Input string * @param params Parameter array * @param nparams Number of parameters * @param GPS_INFO GPS_INFO struct to parse into * @return Parsing success */ bool NMEAParser::RMC(NMEAInputLine &line, NMEA_INFO *GPS_INFO) { fixed ThisTime = TimeModify(line.read(fixed_zero), GPS_INFO->DateTime); gpsValid = !NAVWarn(line.read_first_char()); GeoPoint location; bool valid_location = ReadGeoPoint(line, location); GPS_STATE &gps = GPS_INFO->gps; gps.Connected = 2; if (!activeGPS) return true; fixed speed = line.read(fixed_zero); gps.MovementDetected = speed > fixed_two; if (gps.Replay) // block actual GPS signal if not moving and a log is being replayed return true; gps.NAVWarning = !gpsValid; fixed TrackBearing = line.read(fixed_zero); // JMW get date info first so TimeModify is accurate char date_buffer[9]; line.read(date_buffer, 9); GPS_INFO->DateTime.year = atoi(&date_buffer[4]) + 2000; date_buffer[4] = '\0'; GPS_INFO->DateTime.month = atoi(&date_buffer[2]); date_buffer[2] = '\0'; GPS_INFO->DateTime.day = atoi(&date_buffer[0]); if (!TimeHasAdvanced(ThisTime, GPS_INFO)) return false; if (valid_location) GPS_INFO->Location = location; else GPS_INFO->gps.NAVWarning = true; GPS_INFO->GroundSpeed = Units::ToSysUnit(speed, unKnots); if (GPS_INFO->GroundSpeed > fixed_one) { // JMW don't update bearing unless we're moving GPS_INFO->TrackBearing = Angle::degrees(TrackBearing).as_bearing(); } if (!gps.Replay) { if (RMZAvailable) { // JMW changed from Altitude to BaroAltitude GPS_INFO->BaroAltitudeAvailable = true; GPS_INFO->BaroAltitude = RMZAltitude; } else if (RMAAvailable) { // JMW changed from Altitude to BaroAltitude GPS_INFO->BaroAltitudeAvailable = true; GPS_INFO->BaroAltitude = RMAAltitude; } } if (!GGAAvailable) { // update SatInUse, some GPS receiver don't emit GGA sentence if (!gpsValid) gps.SatellitesUsed = 0; else gps.SatellitesUsed = -1; } // say we are updated every time we get this, // so infoboxes get refreshed if GPS connected TriggerGPSUpdate(); return true; }
bool NMEAParser::RMC(NMEAInputLine &line, NMEAInfo &info) { /* * $--RMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,xxxx,x.x,a,m,*hh * * Field Number: * 1) UTC Time * 2) Status, V=Navigation receiver warning A=Valid * 3) Latitude * 4) N or S * 5) Longitude * 6) E or W * 7) Speed over ground, knots * 8) Track made good, degrees true * 9) Date, ddmmyy * 10) Magnetic Variation, degrees * 11) E or W * 12) FAA mode indicator (NMEA 2.3 and later) * 13) Checksum */ fixed this_time = line.read(fixed_zero); bool gps_valid = !NAVWarn(line.read_first_char()); GeoPoint location; bool valid_location = ReadGeoPoint(line, location); fixed speed; bool ground_speed_available = line.read_checked(speed); fixed track; bool track_available = line.read_checked(track); // JMW get date info first so TimeModify is accurate if (ReadDate(line, info.date_time_utc)) info.date_available = true; this_time = TimeModify(this_time, info.date_time_utc, info.date_available); this_time = TimeAdvanceTolerance(this_time); if (!TimeHasAdvanced(this_time, info)) return true; if (!gps_valid) info.location_available.Clear(); else if (valid_location) info.location_available.Update(info.clock); if (valid_location) info.location = location; if (ground_speed_available) { info.ground_speed = Units::ToSysUnit(speed, unKnots); info.ground_speed_available.Update(info.clock); } if (track_available && info.MovementDetected()) { // JMW don't update bearing unless we're moving info.track = Angle::Degrees(track).AsBearing(); info.track_available.Update(info.clock); } info.gps.real = real; #ifdef ANDROID info.gps.android_internal_gps = false; #endif return true; }
/** * Parse a "$FLYSEN" sentence. * * @see http://www.flytec.ch/public/Special%20NMEA%20sentence.pdf */ static bool FlytecParseFLYSEN(NMEAInputLine &line, NMEA_INFO &info) { fixed value; // Time(hhmmss), 6 Digits line.skip(); // Latitude(ddmm.mmm), 8 Digits incl. decimal // N (or S), 1 Digit line.skip(2); // Longitude(dddmm.mmm), 9 Digits inc. decimal // E (or W), 1 Digit line.skip(2); // Track (xxx Deg), 3 Digits // Speed over Ground (xxxxx cm/s) 5 Digits // GPS altitude (xxxxx meter), 5 Digits line.skip(3); // Validity of 3 D fix A or V, 1 Digit char validity = line.read_first_char(); if (validity != 'A' && validity != 'V') { validity = line.read_first_char(); if (validity != 'A' && validity != 'V') return false; } // Satellites in Use (0 to 12), 2 Digits line.skip(); // Raw pressure (xxxxxx Pa), 6 Digits if (line.read_checked(value)) info.ProvideStaticPressure(value / 100); // Baro Altitude (xxxxx meter), 5 Digits (-xxxx to xxxxx) (Based on 1013.25hPa) if (line.read_checked(value)) info.ProvidePressureAltitude(value); // Variometer (xxxx cm/s), 4 or 5 Digits (-9999 to 9999) if (line.read_checked(value)) info.ProvideTotalEnergyVario(value / 100); // true airspeed (xxxxx cm/s), 5 Digits (0 to 99999cm/s = 3600km/h) if (line.read_checked(value)) info.ProvideTrueAirspeed(value / 100); // Airspeed source P or V, 1 Digit P= pitot, V = Vane wheel // Temp. PCB (xxx °C), 3 Digits // Temp. Balloon Envelope (xxx °C), 3 Digits // Battery Capacity Bank 1 (0 to 100%) 3 Digits // Battery Capacity Bank 2 (0 to 100%) 3 Digits // Dist. to WP (xxxxxx m), 6 Digits (Max 200000m) // Bearing (xxx Deg), 3 Digits // Speed to fly1 (MC0 xxxxx cm/s), 5 Digits // Speed to fly2 (McC. xxxxx cm/s) 5 Digits // Keypress Code (Experimental empty to 99) 2 Digits return true; }