static bool PZAN3(NMEAInputLine &line, NMEAInfo &info) { // old: $PZAN3,+,026,V,321,035,A,321,035,V*cc // new: $PZAN3,+,026,A,321,035,V[,A]*cc line.Skip(3); int direction, speed; if (!line.ReadChecked(direction) || !line.ReadChecked(speed)) return false; char okay = line.ReadFirstChar(); if (okay == 'V') { okay = line.ReadFirstChar(); if (okay == 'V') return true; if (okay != 'A') { line.Skip(); okay = line.ReadFirstChar(); } } if (okay == 'A') { SpeedVector wind(Angle::Degrees(direction), Units::ToSysUnit(fixed(speed), Unit::KILOMETER_PER_HOUR)); info.ProvideExternalWind(wind); } return true; }
/** * $PWES1,DD,MM,S,AAA,F,V,LLL,BB*CS<CR><LF> */ static bool PWES1(NMEAInputLine &line, NMEAInfo &info) { line.Skip(); /* device */ int i; if (line.ReadChecked(i)) info.settings.ProvideMacCready(fixed(i) / 10, info.clock); info.switch_state.flight_mode = SwitchState::FlightMode::UNKNOWN; if (line.ReadChecked(i)) { if (i == 0) info.switch_state.flight_mode = SwitchState::FlightMode::CIRCLING; else if (i == 1) info.switch_state.flight_mode = SwitchState::FlightMode::CRUISE; } line.Skip(3); if (line.ReadChecked(i)) info.settings.ProvideWingLoading(fixed(i) / 10, info.clock); if (line.ReadChecked(i)) info.settings.ProvideBugs(fixed(100 - i) / 100, info.clock); return true; }
/** * $PWES1,DD,MM,S,AAA,F,V,LLL,BB*CS<CR><LF> */ static bool PWES1(NMEAInputLine &line, NMEAInfo &info) { line.Skip(); /* device */ int i; if (line.ReadChecked(i)) info.settings.ProvideMacCready(fixed(i) / 10, info.clock); if (line.ReadChecked(i)) { if (i == 0) { info.switch_state.flight_mode = SwitchInfo::FlightMode::CIRCLING; info.switch_state.speed_command = false; info.switch_state_available = true; } else if (i == 1) { info.switch_state.flight_mode = SwitchInfo::FlightMode::CRUISE; info.switch_state.speed_command = true; info.switch_state_available = true; } } line.Skip(3); if (line.ReadChecked(i)) info.settings.ProvideWingLoading(fixed(i) / 10, info.clock); if (line.ReadChecked(i)) info.settings.ProvideBugs(fixed(100 - i) / 100, info.clock); return true; }
static bool ParseAPENV1(NMEAInputLine &line, NMEAInfo &info) { // $APENV1,IAS,Altitude,0,0,0,VerticalSpeed, int ias; if (!line.ReadChecked(ias)) return false; int altitude; if (!line.ReadChecked(altitude)) return false; line.Skip(); line.Skip(); line.Skip(); // In ft/min, quality of this is limited, do not use for the time being int vs; if (!line.ReadChecked(vs)) return false; auto sys_alt = Units::ToSysUnit(fixed(altitude), Unit::FEET); info.ProvidePressureAltitude(sys_alt); info.ProvideIndicatedAirspeedWithAltitude(Units::ToSysUnit(fixed(ias), Unit::KNOTS), sys_alt); return true; }
static bool PTFRS(NMEAInputLine &line, NMEAInfo &info) { // $PTFRS,1,0,0,0,0,0,0,0,5,1,10,0,3,1338313437,0,0,0,,,2*4E // // $PTFRS,<sealed>,<downloadmode>,<event>,<neartp>,<sealing>,<baromode>, // <decllock>,<newrecavail>,<enl>,<rpm>,<interval>,<error>,<timbase>, // <time>,<secpower>,<secpowerint>,<usup>,<ulit>, // <chargerstate>,<antstate>*CS<CR><LF> line.Skip(8); unsigned enl; if (line.ReadChecked(enl)) { info.engine_noise_level = enl; info.engine_noise_level_available.Update(info.clock); } line.Skip(7); unsigned supply_voltage; if (line.ReadChecked(supply_voltage) && supply_voltage != 0) { info.voltage = fixed(supply_voltage) / 1000; info.voltage_available.Update(info.clock); } return true; }
/** * $PWES0,DD,VVVV,MMMM,NNNN,BBBB,SSSS,AAAAA,QQQQQ,IIII,TTTT,UUU,CCCC*CS<CR><LF> */ static bool PWES0(NMEAInputLine &line, NMEAInfo &info) { int i; line.Skip(); /* device */ if (line.ReadChecked(i) && i >= -999 && i <= 999) info.ProvideTotalEnergyVario(fixed(i) / 10); line.Skip(); /* average vario */ if (line.ReadChecked(i) && i >= -999 && i <= 999) info.ProvideNettoVario(fixed(i) / 10); line.Skip(); /* average netto vario */ line.Skip(); /* speed to fly */ unsigned altitude; if (line.ReadChecked(altitude) && altitude <= 99999) info.ProvidePressureAltitude(fixed(altitude)); if (line.ReadChecked(altitude) && altitude <= 99999) info.ProvideBaroAltitudeTrue(fixed(altitude)); unsigned ias, tas; bool have_ias = line.ReadChecked(ias) && ias <= 9999; bool have_tas = line.ReadChecked(tas) && tas <= 9999; if (have_ias && have_tas) info.ProvideBothAirspeeds(Units::ToSysUnit(fixed(ias) / 10, Unit::KILOMETER_PER_HOUR), Units::ToSysUnit(fixed(tas) / 10, Unit::KILOMETER_PER_HOUR)); else if (!have_ias && have_tas) info.ProvideTrueAirspeed(Units::ToSysUnit(fixed(tas) / 10, Unit::KILOMETER_PER_HOUR)); unsigned voltage; if (line.ReadChecked(voltage) && voltage <= 999) { info.voltage = fixed(voltage) / 10; info.voltage_available.Update(info.clock); } if (line.ReadChecked(i) && i >= -999 && i <= 999) { info.temperature = CelsiusToKelvin(fixed(i) / 10); info.temperature_available = true; } return true; }
/** * Parse a "$VMVABD" sentence. * * Example: "$VMVABD,0000.0,M,0547.0,M,-0.0,,,MS,0.0,KH,22.4,C*65" */ static bool FlytecParseVMVABD(NMEAInputLine &line, NMEAInfo &info) { fixed value; // 0,1 = GPS altitude, unit if (line.ReadCheckedCompare(info.gps_altitude, "M")) info.gps_altitude_available.Update(info.clock); // 2,3 = baro altitude, unit if (line.ReadCheckedCompare(value, "M")) info.ProvideBaroAltitudeTrue(value); // 4-7 = integrated vario, unit line.Skip(4); // 8,9 = indicated or true airspeed, unit if (line.ReadCheckedCompare(value, "KH")) // XXX is that TAS or IAS? Documentation isn't clear. info.ProvideBothAirspeeds(Units::ToSysUnit(value, Unit::KILOMETER_PER_HOUR)); // 10,11 = temperature, unit info.temperature_available = line.ReadCheckedCompare(value, "C"); if (info.temperature_available) info.temperature = CelsiusToKelvin(value); return true; }
bool NMEAParser::GSA(NMEAInputLine &line, NMEAInfo &info) { /* * $--GSA,a,a,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x.x,x.x,x.x*hh * * Field Number: * 1) Selection mode * M=Manual, forced to operate in 2D or 3D * A=Automatic, 3D/2D * 2) Mode (1 = no fix, 2 = 2D fix, 3 = 3D fix) * 3) ID of 1st satellite used for fix * 4) ID of 2nd satellite used for fix * ... * 14) ID of 12th satellite used for fix * 15) PDOP * 16) HDOP * 17) VDOP * 18) checksum */ line.Skip(); if (line.Read(0) == 1) info.location_available.Clear(); // satellites are in items 4-15 of GSA string (4-15 is 1-indexed) for (unsigned i = 0; i < GPSState::MAXSATELLITES; i++) info.gps.satellite_ids[i] = line.Read(0); info.gps.satellite_ids_available.Update(info.clock); return true; }
// RMN: Volkslogger // Source data: // $PGCS,1,0EC0,FFF9,0C6E,02*61 // $PGCS,1,0EC0,FFFA,0C6E,03*18 static bool vl_PGCS1(NMEAInputLine &line, NMEAInfo &info) { if (line.Read(1) != 1) return false; /* pressure sensor */ line.Skip(); // four characers, hex, barometric altitude unsigned u_altitude; if (line.ReadHexChecked(u_altitude)) { int altitude(u_altitude); if (altitude > 60000) /* Assuming that altitude has wrapped around. 60 000 m occurs at QNH ~2000 hPa */ altitude -= 65535; info.ProvidePressureAltitude(fixed(altitude)); } // ExtractParameter(String,ctemp,3); // four characters, hex, constant. Value 1371 (dec) // nSatellites = (int)(min(12,HexStrToDouble(ctemp, NULL))); return false; }
// $PDVDS,nx,nz,flap,stallratio,netto static bool PDVDS(NMEAInputLine &line, NMEAInfo &info) { fixed AccelX = line.Read(fixed_zero); fixed AccelZ = line.Read(fixed_zero); fixed mag = SmallHypot(AccelX, AccelZ); info.acceleration.ProvideGLoad(fixed(mag) / 100, true); /* double flap = line.Read(0.0); */ line.Skip(); info.stall_ratio = line.Read(fixed_zero); info.stall_ratio_available.Update(info.clock); fixed value; if (line.ReadChecked(value)) info.ProvideNettoVario(value / 10); //hasVega = true; return true; }
static bool LXWP0(NMEAInputLine &line, NMEAInfo &info) { /* $LXWP0,Y,222.3,1665.5,1.71,,,,,,239,174,10.1 0 loger_stored (Y/N) 1 IAS (kph) ----> Condor uses TAS! 2 baroaltitude (m) 3-8 vario (m/s) (last 6 measurements in last second) 9 heading of plane 10 windcourse (deg) 11 windspeed (kph) */ line.Skip(); fixed airspeed; bool tas_available = line.ReadChecked(airspeed); if (tas_available && (airspeed < fixed(-50) || airspeed > fixed(250))) /* implausible */ return false; fixed value; if (line.ReadChecked(value)) /* a dump on a LX7007 has confirmed that the LX sends uncorrected altitude above 1013.25hPa here */ info.ProvidePressureAltitude(value); if (tas_available) /* * Call ProvideTrueAirspeed() after ProvidePressureAltitude() to use * the provided altitude (if available) */ info.ProvideTrueAirspeed(Units::ToSysUnit(airspeed, Unit::KILOMETER_PER_HOUR)); if (line.ReadChecked(value)) info.ProvideTotalEnergyVario(value); line.Skip(6); SpeedVector wind; if (ReadSpeedVector(line, wind)) info.ProvideExternalWind(wind); return true; }
static void ParseNanoInfo(NMEAInputLine &line, DeviceInfo &device) { ReadString(line, device.product); ReadString(line, device.software_version); line.Skip(); /* ver.date, e.g. "May 12 2012 21:38:28" */ ReadString(line, device.hardware_version); }
static bool cLXWP0(NMEAInputLine &line, NMEAInfo &info) { /* $LXWP0,Y,222.3,1665.5,1.71,,,,,,239,174,10.1 0 logger_stored (Y/N) 1 IAS (kph) ----> Condor uses TAS! 2 baroaltitude (m) 3 vario (m/s) 4-8 unknown 9 heading of plane 10 windcourse (deg) 11 windspeed (kph) */ fixed value; line.Skip(); fixed airspeed; bool tas_available = line.ReadChecked(airspeed); fixed alt = line.Read(fixed_zero); if (tas_available) info.ProvideTrueAirspeedWithAltitude(Units::ToSysUnit(airspeed, Unit::KILOMETER_PER_HOUR), alt); // ToDo check if QNH correction is needed! info.ProvideBaroAltitudeTrue(alt); if (line.ReadChecked(value)) info.ProvideTotalEnergyVario(value); line.Skip(6); SpeedVector wind; if (ReadSpeedVector(line, wind)) info.ProvideExternalWind(wind); return true; }
static bool GPWIN(NMEAInputLine &line, NMEAInfo &info) { line.Skip(2); fixed value; if (line.ReadChecked(value)) info.ProvidePressureAltitude(value / 10); return false; }
void ParsePFLAU(NMEAInputLine &line, FlarmStatus &flarm, double clock) { flarm.available.Update(clock); // PFLAU,<RX>,<TX>,<GPS>,<Power>,<AlarmLevel>,<RelativeBearing>,<AlarmType>, // <RelativeVertical>,<RelativeDistance>(,<ID>) flarm.rx = line.Read(0); flarm.tx = line.Read(false); flarm.gps = (FlarmStatus::GPSStatus) line.Read((int)FlarmStatus::GPSStatus::NONE); line.Skip(); flarm.alarm_level = (FlarmTraffic::AlarmType) line.Read((int)FlarmTraffic::AlarmType::NONE); }
bool NMEAParser::PTAS1(NMEAInputLine &line, NMEAInfo &info) { /* * $PTAS1,xxx,yyy,zzzzz,aaa*CS<CR><LF> * * xxx * CV or current vario. =vario*10+200 range 0-400(display +/-20.0 knots) * * yyy * AV or average vario. =vario*10+200 range 0-400(display +/-20.0 knots) * * zzzzz * Barometric altitude in feet +2000 * * aaa * TAS knots 0-200 */ // Parse current vario data fixed vario; if (line.ReadChecked(vario)) { // Properly convert to m/s vario = Units::ToSysUnit((vario - fixed(200)) / 10, Unit::KNOTS); info.ProvideTotalEnergyVario(vario); } // Skip average vario data line.Skip(); // Parse barometric altitude fixed baro_altitude; if (line.ReadChecked(baro_altitude)) { // Properly convert to meter baro_altitude = Units::ToSysUnit(baro_altitude - fixed(2000), Unit::FEET); info.ProvidePressureAltitude(baro_altitude); } // Parse true airspeed fixed vtas; if (line.ReadChecked(vtas)) info.ProvideTrueAirspeed(Units::ToSysUnit(vtas, Unit::KNOTS)); return true; }
// PDTSM,duration_ms,"free text" static bool PDTSM(NMEAInputLine &line, gcc_unused NMEAInfo &info) { /* int duration = (int)strtol(String, nullptr, 10); */ line.Skip(); const auto message = line.Rest(); StaticString<256> buffer; buffer.SetASCII(message.begin(), message.end()); // todo duration handling Message::AddMessage(_T("VEGA:"), buffer); return true; }
/** * Parse a "$PDGFTL1" sentence. * * Example: "$PDGFTL1,2025,2000,250,-14,45,134,28,65,382,153*3D" */ static bool PDGFTL1(NMEAInputLine &line, NMEAInfo &info) { double value; // Baro Altitude QNE(1013.25) 2025 meter 2025 mt if (line.ReadChecked(value)) info.ProvidePressureAltitude(value); // Baro Altitude QNH 2000 meter 2000 mt if (line.ReadChecked(value)) info.ProvideBaroAltitudeTrue(value); // Vario 250 cm/sec +2,50 m/s if (line.ReadChecked(value)) info.ProvideTotalEnergyVario(value / 100); // Netto Vario -14 dm/sec -1,40 m/s if (line.ReadChecked(value)) info.ProvideNettoVario(value / 10); // Indicated Air Speed 45 km/h 45 km/h if (line.ReadChecked(value)) info.ProvideIndicatedAirspeed(Units::ToSysUnit(value, Unit::KILOMETER_PER_HOUR)); // Ground Efficiency 134 ratio 13,4 : 1 line.Skip(); // Wind Speed 28 km/h 28 km/h // Wind Direction 65 degree 65 degree SpeedVector wind; if (ReadSpeedVector(line, wind)) info.ProvideExternalWind(wind); // Main Lithium Battery Voltage 382 0.01 volts 3,82 volts if (line.ReadChecked(value)) { info.voltage = value / 100; info.voltage_available.Update(info.clock); } // Backup AA Battery Voltage 153 0.01 volts 1,53 volts return true; }
/** * Parse a "$D" sentence. * * Example: "$D,+0,100554,+25,18,+31,,0,-356,+25,+11,115,96*6A" */ static bool LeonardoParseD(NMEAInputLine &line, NMEAInfo &info) { fixed value; // 0 = vario [dm/s] if (line.ReadChecked(value)) info.ProvideTotalEnergyVario(value / 10); // 1 = air pressure [Pa] if (line.Skip() == 0) /* short "$C" sentence ends after airspeed */ return true; // 2 = netto vario [dm/s] if (line.ReadChecked(value)) info.ProvideNettoVario(value / 10); // 3 = airspeed [km/h] /* XXX is that TAS or IAS? */ if (line.ReadChecked(value)) info.ProvideTrueAirspeed(Units::ToSysUnit(value, Unit::KILOMETER_PER_HOUR)); // 4 = temperature [deg C] fixed oat; info.temperature_available = line.ReadChecked(oat); if (info.temperature_available) info.temperature = CelsiusToKelvin(oat); // 5 = compass [degrees] /* XXX unsupported by XCSoar */ // 6 = optimal speed [km/h] /* XXX unsupported by XCSoar */ // 7 = equivalent MacCready [cm/s] /* XXX unsupported by XCSoar */ // 8 = wind speed [km/h] /* not used here, the "$C" record repeats it together with the direction */ return true; }
/** * Parse a "$C" sentence. * * Example: "$C,+2025,-7,+18,+25,+29,122,314,314,0,-356,+25,45,T*3D" */ static bool LeonardoParseC(NMEAInputLine &line, NMEAInfo &info) { double value; // 0 = altitude [m] if (line.ReadChecked(value)) info.ProvideBaroAltitudeTrue(value); // 1 = vario [cm/s] if (line.ReadChecked(value)) info.ProvideTotalEnergyVario(value / 100); // 2 = airspeed [km/h] /* XXX is that TAS or IAS? */ if (line.ReadChecked(value)) info.ProvideTrueAirspeed(Units::ToSysUnit(value, Unit::KILOMETER_PER_HOUR)); if (line.Rest().empty()) /* short "$C" sentence ends after airspeed */ return true; // 3 = netto vario [dm/s] if (line.ReadChecked(value)) info.ProvideNettoVario(value / 10); // 4 = temperature [deg C] double oat; info.temperature_available = line.ReadChecked(oat); if (info.temperature_available) info.temperature = CelsiusToKelvin(oat); line.Skip(5); // 10 = wind speed [km/h] // 11 = wind direction [degrees] SpeedVector wind; if (ReadSpeedVector(line, wind)) info.ProvideExternalWind(wind); return true; }
static bool LXWP2(NMEAInputLine &line, NMEAInfo &info) { /* * $LXWP2, * maccready value, (m/s) * ballast, (1.0 - 1.5) * bugs, (0 - 100%) * polar_a, * polar_b, * polar_c, * audio volume */ fixed value; // MacCready value if (line.ReadChecked(value)) info.settings.ProvideMacCready(value, info.clock); // Ballast if (line.ReadChecked(value)) info.settings.ProvideBallastOverload(value, info.clock); // Bugs if (line.ReadChecked(value)) { if (value <= fixed(1.5) && value >= fixed(1.0)) // LX160 (sw 3.04) reports bugs as 1.00, 1.05 or 1.10 (#2167) info.settings.ProvideBugs(fixed(2) - value, info.clock); else // All other known LX devices report bugs as 0, 5, 10, 15, ... info.settings.ProvideBugs((fixed(100) - value) / 100, info.clock); } line.Skip(3); unsigned volume; if (line.ReadChecked(volume)) info.settings.ProvideVolume(volume, info.clock); return true; }
/** * Parse the $PLXVF sentence (LXNav V7). * * $PLXVF,time ,AccX,AccY,AccZ,Vario,IAS,PressAlt*CS<CR><LF> * * Example: $PLXVF,1.00,0.87,-0.12,-0.25,90.2,244.3,*CS<CR><LF> * * @see http://www.xcsoar.org/trac/raw-attachment/ticket/1666/V7%20dataport%20specification%201.97.pdf */ static bool PLXVF(NMEAInputLine &line, NMEAInfo &info) { line.Skip(4); fixed vario; if (line.ReadChecked(vario)) info.ProvideNettoVario(vario); fixed ias; bool have_ias = line.ReadChecked(ias); fixed altitude; if (line.ReadChecked(altitude)) { info.ProvidePressureAltitude(altitude); if (have_ias) info.ProvideIndicatedAirspeedWithAltitude(ias, altitude); } return true; }
// PDTSM,duration_ms,"free text" static bool PDTSM(NMEAInputLine &line, gcc_unused NMEAInfo &info) { /* int duration = (int)strtol(String, NULL, 10); */ line.Skip(); const char *message = line.Rest(); #ifdef _UNICODE TCHAR buffer[strlen(message)]; if (MultiByteToWideChar(CP_ACP, 0, message, -1, buffer, ARRAY_SIZE(buffer)) <= 0) return false; #else const char *buffer = message; #endif // todo duration handling Message::AddMessage(_T("VEGA:"), buffer); return true; }
// $PDVDS,nx,nz,flap,stallratio,netto static bool PDVDS(NMEAInputLine &line, NMEAInfo &info) { const int accel_x = line.Read(0), accel_z = line.Read(0); fixed mag = SmallHypot(fixed(accel_x), fixed(accel_z)); info.acceleration.ProvideGLoad(mag / 100, true); /* double flap = line.Read(0.0); */ line.Skip(); info.stall_ratio = line.Read(fixed(0)); info.stall_ratio_available.Update(info.clock); int value; if (line.ReadChecked(value)) info.ProvideNettoVario(fixed(value) / 10); //hasVega = true; return true; }
void ParsePFLAA(NMEAInputLine &line, TrafficList &flarm, double clock) { flarm.modified.Update(clock); // PFLAA,<AlarmLevel>,<RelativeNorth>,<RelativeEast>,<RelativeVertical>, // <IDType>,<ID>,<Track>,<TurnRate>,<GroundSpeed>,<ClimbRate>,<AcftType> FlarmTraffic traffic; traffic.alarm_level = (FlarmTraffic::AlarmType) line.Read((int)FlarmTraffic::AlarmType::NONE); double value; bool stealth = false; if (!line.ReadChecked(value)) // Relative North is required ! return; traffic.relative_north = value; if (!line.ReadChecked(value)) // Relative East is required ! return; traffic.relative_east = value; if (!line.ReadChecked(value)) // Relative Altitude is required ! return; traffic.relative_altitude = value; line.Skip(); /* id type */ // 5 id, 6 digit hex char id_string[16]; line.Read(id_string, 16); traffic.id = FlarmId::Parse(id_string, nullptr); Angle track; traffic.track_received = ReadBearing(line, track); if (!traffic.track_received) { // Field is empty in stealth mode stealth = true; traffic.track = Angle::Zero(); } else traffic.track = track; traffic.turn_rate_received = line.ReadChecked(value); if (!traffic.turn_rate_received) { // Field is empty in stealth mode traffic.turn_rate = 0; } else traffic.turn_rate = value; traffic.speed_received = line.ReadChecked(value); if (!traffic.speed_received) { // Field is empty in stealth mode stealth = true; traffic.speed = 0; } else traffic.speed = value; traffic.climb_rate_received = line.ReadChecked(value); if (!traffic.climb_rate_received) { // Field is empty in stealth mode stealth = true; traffic.climb_rate = 0; } else traffic.climb_rate = value; traffic.stealth = stealth; unsigned type = line.Read(0); if (type > 15 || type == 14) traffic.type = FlarmTraffic::AircraftType::UNKNOWN; else traffic.type = (FlarmTraffic::AircraftType)type; FlarmTraffic *flarm_slot = flarm.FindTraffic(traffic.id); if (flarm_slot == nullptr) { flarm_slot = flarm.AllocateTraffic(); if (flarm_slot == nullptr) // no more slots available return; flarm_slot->Clear(); flarm_slot->id = traffic.id; flarm.new_traffic.Update(clock); } // set time of fix to current time flarm_slot->valid.Update(clock); flarm_slot->Update(traffic); }
/** * Parse a "$FLYSEN" sentence. * * @see http://www.flytec.ch/public/Special%20NMEA%20sentence.pdf */ bool FlytecDevice::ParseFLYSEN(NMEAInputLine &line, NMEAInfo &info) { // Detect firmware/sentence version // // V or A in field 9 -> 3.31- // V or A in field 10 -> 3.32+ NMEAInputLine line_copy(line); line_copy.Skip(8); bool has_date_field = false; char validity = line_copy.ReadFirstChar(); if (validity != 'A' && validity != 'V') { validity = line_copy.ReadFirstChar(); if (validity != 'A' && validity != 'V') return false; has_date_field = true; } // Date(ddmmyy), 6 Digits (only in firmware version 3.32+) if (has_date_field) NMEAParser::ReadDate(line, info.date_time_utc); // Time(hhmmss), 6 Digits fixed time; if (NMEAParser::ReadTime(line, info.date_time_utc, time) && !NMEAParser::TimeHasAdvanced(time, last_time, info)) return true; if (validity == 'V') { // In case of V (void=not valid) GPS data should not be used. // GPS altitude, position and speed should be ignored. line.Skip(7); } else { // Latitude(ddmm.mmm), 8 Digits incl. decimal // N (or S), 1 Digit // Longitude(dddmm.mmm), 9 Digits inc. decimal // E (or W), 1 Digit GeoPoint location; if (NMEAParser::ReadGeoPoint(line, location)) { info.location = location; info.location_available.Update(info.clock); } // Track (xxx Deg), 3 Digits fixed track; if (line.ReadChecked(track)) { info.track = Angle::Degrees(track); info.track_available.Update(info.clock); } // Speed over Ground (xxxxx dm/s), 5 Digits fixed ground_speed; if (line.ReadChecked(ground_speed)) { info.ground_speed = ground_speed / 10; info.ground_speed_available.Update(info.clock); } // GPS altitude (xxxxx meter), 5 Digits fixed gps_altitude; if (line.ReadChecked(gps_altitude)) { info.gps_altitude = gps_altitude; info.gps_altitude_available.Update(info.clock); } } // Validity of 3 D fix A or V, 1 Digit line.Skip(); // Satellites in Use (0 to 12), 2 Digits unsigned satellites_used; if (line.ReadChecked(satellites_used)) { info.gps.satellites_used = satellites_used; info.gps.satellites_used_available.Update(info.clock); } // Raw pressure (xxxxxx Pa), 6 Digits fixed pressure; if (line.ReadChecked(pressure)) info.ProvideStaticPressure(AtmosphericPressure::Pascal(pressure)); // Baro Altitude (xxxxx meter), 5 Digits (-xxxx to xxxxx) (Based on 1013.25hPa) fixed baro_altitude; if (line.ReadChecked(baro_altitude)) info.ProvidePressureAltitude(baro_altitude); // Variometer (xxxx cm/s), 4 or 5 Digits (-9999 to 9999) fixed vario; if (line.ReadChecked(vario)) info.ProvideTotalEnergyVario(vario / 100); // True airspeed (xxxxx dm/s), 5 Digits fixed tas; if (line.ReadChecked(tas)) info.ProvideTrueAirspeed(tas / 10); // Airspeed source P or V, 1 Digit P= pitot, V = Vane wheel line.Skip(); // Temp. PCB (xxx °C), 3 Digits fixed pcb_temperature; bool pcb_temperature_available = line.ReadChecked(pcb_temperature); // Temp. Balloon Envelope (xxx °C), 3 Digits fixed balloon_temperature; bool balloon_temperature_available = line.ReadChecked(balloon_temperature); if (balloon_temperature_available) { info.temperature = CelsiusToKelvin(balloon_temperature); info.temperature_available = true; } else if (pcb_temperature_available) { info.temperature = CelsiusToKelvin(pcb_temperature); info.temperature_available = true; } // Battery Capacity Bank 1 (0 to 100%) 3 Digits fixed battery_level_1; bool battery_level_1_available = line.ReadChecked(battery_level_1); // Battery Capacity Bank 2 (0 to 100%) 3 Digits fixed battery_level_2; bool battery_level_2_available = line.ReadChecked(battery_level_2); if (battery_level_1_available) { if (battery_level_2_available) info.battery_level = (battery_level_1 + battery_level_2) / 2; else info.battery_level = battery_level_1; info.battery_level_available.Update(info.clock); } else if (battery_level_2_available) { info.battery_level = battery_level_2; info.battery_level_available.Update(info.clock); } // 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; }