/** * $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.read_checked(i)) info.settings.ProvideMacCready(fixed(i) / 10, info.clock); if (line.read_checked(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.read_checked(i)) info.settings.ProvideWingLoading(fixed(i) / 10, info.clock); if (line.read_checked(i)) info.settings.ProvideBugs(fixed(100 - i) / 100, info.clock); return true; }
static bool LXWP2(NMEAInputLine &line, NMEA_INFO *GPS_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.read_checked(value)) GPS_INFO->MacCready = value; // Ballast line.skip(); /* if (line.read_checked(value)) GPS_INFO->Ballast = value; */ // Bugs if (line.read_checked(value)) GPS_INFO->Bugs = fixed(100) - value; return true; }
static bool LXWP2(NMEAInputLine &line, NMEA_INFO *GPS_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.read_checked(value)) GPS_INFO->settings.ProvideMacCready(value, GPS_INFO->Time); // Ballast line.skip(); /* if (line.read_checked(value)) GPS_INFO->ProvideBallast(value, GPS_INFO->Time); */ // Bugs if (line.read_checked(value)) GPS_INFO->settings.ProvideBugs((fixed(100) - value) / 100, GPS_INFO->Time); return true; }
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.read_checked(direction) || !line.read_checked(speed)) return false; char okay = line.read_first_char(); if (okay == 'V') { okay = line.read_first_char(); if (okay == 'V') return true; if (okay != 'A') { line.skip(); okay = line.read_first_char(); } } if (okay == 'A') { SpeedVector wind(Angle::Degrees(fixed(direction)), Units::ToSysUnit(fixed(speed), unKiloMeterPerHour)); info.ProvideExternalWind(wind); } 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 info NMEA_INFO struct to parse into * @return Parsing success */ bool NMEAParser::RMC(NMEAInputLine &line, NMEAInfo &info) { fixed ThisTime = line.read(fixed_zero); bool gpsValid = !NAVWarn(line.read_first_char()); GeoPoint location; bool valid_location = ReadGeoPoint(line, location); GPSState &gps = info.gps; fixed speed; bool GroundSpeedAvailable = 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; ThisTime = TimeModify(ThisTime, info.date_time_utc, info.date_available); ThisTime = TimeAdvanceTolerance(ThisTime); if (!TimeHasAdvanced(ThisTime, info)) return true; if (!gpsValid) info.location_available.Clear(); else if (valid_location) info.location_available.Update(info.clock); if (valid_location) info.location = location; if (GroundSpeedAvailable) { 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).as_bearing(); info.track_available.Update(info.clock); } if (!GGAAvailable) { // update SatInUse, some GPS receiver don't emit GGA sentence gps.satellites_used = -1; } info.gps.real = real; #ifdef ANDROID info.gps.android_internal_gps = false; #endif return true; }
static bool PDVVT(NMEAInputLine &line, NMEAInfo &info) { fixed value; info.temperature_available = line.read_checked(value); if (info.temperature_available) info.temperature = value / 10; info.humidity_available = line.read_checked(info.humidity); return true; }
static bool PZAN2(NMEAInputLine &line, NMEAInfo &info) { fixed vtas, wnet; if (line.read_checked(vtas)) info.ProvideTrueAirspeed(Units::ToSysUnit(vtas, unKiloMeterPerHour)); if (line.read_checked(wnet)) info.ProvideTotalEnergyVario((wnet - fixed(10000)) / 100); return true; }
static bool ReadSpeedVector(NMEAInputLine &line, SpeedVector &value_r) { fixed bearing, norm; bool bearing_valid = line.read_checked(bearing); bool norm_valid = line.read_checked(norm); if (bearing_valid && norm_valid) { value_r.bearing = Angle::degrees(bearing); value_r.norm = Units::ToSysUnit(norm, unKiloMeterPerHour); return true; } else 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); int mag = (int)hypot(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.read_checked(value)) info.ProvideNettoVario(value / 10); //hasVega = true; return true; }
static bool ReadFixedAndChar(NMEAInputLine &line, fixed &d, char &ch) { bool success = line.read_checked(d); ch = line.read_first_char(); return success; }
static bool ReadSpeedVector(NMEAInputLine &line, SpeedVector &value_r) { fixed bearing, norm; bool bearing_valid = line.read_checked(bearing); bool norm_valid = line.read_checked(norm); if (bearing_valid && norm_valid) { value_r.bearing = Angle::degrees(bearing); value_r.norm = norm / 10; return true; } return false; }
/* $PCAID,<1>,<2>,<3>,<4>*hh<CR><LF> <1> Logged 'L' Last point Logged 'N' Last Point not logged <2> Barometer Altitude in meters (Leading zeros will be transmitted) <3> Engine Noise Level <4> Log Flags *hh Checksum, XOR of all bytes of the sentence after the $ and before the * */ static bool cai_PCAID(NMEAInputLine &line, NMEAInfo &data) { line.skip(); fixed value; if (line.read_checked(value)) data.ProvidePressureAltitude(value); unsigned enl; if (line.read_checked(enl)) { data.engine_noise_level = enl; data.engine_noise_level_available.Update(data.clock); } return true; }
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.read_checked(vario)) { // Properly convert to m/s vario = Units::ToSysUnit((vario - fixed(200)) / 10, unKnots); info.ProvideTotalEnergyVario(vario); } // Skip average vario data line.skip(); // Parse barometric altitude fixed baro_altitude; if (line.read_checked(baro_altitude)) { // Properly convert to meter baro_altitude = Units::ToSysUnit(baro_altitude - fixed(2000), unFeet); info.ProvidePressureAltitude(baro_altitude); } // Parse true airspeed fixed vtas; if (line.read_checked(vtas)) info.ProvideTrueAirspeed(Units::ToSysUnit(vtas, unKnots)); return true; }
static bool LXWP0(NMEAInputLine &line, NMEA_INFO *GPS_INFO, bool enable_baro) { /* $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; GPS_INFO->AirspeedAvailable = line.read_checked(airspeed); fixed alt = line.read(fixed_zero); if (GPS_INFO->AirspeedAvailable) { GPS_INFO->TrueAirspeed = Units::ToSysUnit(airspeed, unKiloMeterPerHour); GPS_INFO->IndicatedAirspeed = GPS_INFO->TrueAirspeed / AtmosphericPressure::AirDensityRatio(alt); } if (enable_baro) { GPS_INFO->BaroAltitudeAvailable = true; GPS_INFO->BaroAltitude = alt; // ToDo check if QNH correction is needed! } GPS_INFO->TotalEnergyVarioAvailable = line.read_checked(GPS_INFO->TotalEnergyVario); line.skip(6); GPS_INFO->ExternalWindAvailable = ReadSpeedVector(line, GPS_INFO->wind); TriggerVarioUpdate(); 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, NMEA_INFO &info) { fixed value; // 0 = vario [dm/s] if (line.read_checked(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.read_checked(value)) info.ProvideNettoVario(value / 10); // 3 = airspeed [km/h] /* XXX is that TAS or IAS? */ if (line.read_checked(value)) info.ProvideTrueAirspeed(Units::ToSysUnit(value, unKiloMeterPerHour)); // 4 = temperature [deg C] fixed oat; info.TemperatureAvailable = line.read_checked(oat); if (info.TemperatureAvailable) info.OutsideAirTemperature = Units::ToSysUnit(oat, unGradCelcius); // 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; }
static bool LXWP0(NMEAInputLine &line, NMEA_INFO *GPS_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) */ fixed value; line.skip(); fixed airspeed; bool tas_available = line.read_checked(airspeed); fixed alt = fixed_zero; if (line.read_checked(alt)) /* a dump on a LX7007 has confirmed that the LX sends uncorrected altitude above 1013.25hPa here */ GPS_INFO->ProvidePressureAltitude(alt); if (tas_available) GPS_INFO->ProvideTrueAirspeedWithAltitude(Units::ToSysUnit(airspeed, unKiloMeterPerHour), alt); if (line.read_checked(value)) GPS_INFO->ProvideTotalEnergyVario(value); line.skip(6); SpeedVector wind; if (ReadSpeedVector(line, wind)) GPS_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.read_checked(i)) info.settings.ProvideMacCready(fixed(i) / 10, info.clock); line.skip(4); if (line.read_checked(i)) info.settings.ProvideWingLoading(fixed(i) / 10, info.clock); if (line.read_checked(i)) info.settings.ProvideBugs(fixed(100 - i) / 100, info.clock); return true; }
static bool PZAN4(NMEAInputLine &line, NMEAInfo &info) { // $PZAN4,1.5,+,20,39,45*cc fixed mc; if (line.read_checked(mc)) info.settings.ProvideMacCready(mc, info.clock); return true; }
static bool GPWIN(NMEAInputLine &line, NMEA_INFO *GPS_INFO) { line.skip(2); fixed value; if (line.read_checked(value)) GPS_INFO->ProvidePressureAltitude(value / 10); return false; }
static bool PZAN4(NMEAInputLine &line, NMEA_INFO *GPS_INFO) { // $PZAN4,1.5,+,20,39,45*cc fixed mc; if (line.read_checked(mc)) GPS_INFO->settings.ProvideMacCready(mc, GPS_INFO->Time); return true; }
static bool PDVDV(NMEAInputLine &line, NMEAInfo &info) { fixed value; if (line.read_checked(value)) info.ProvideTotalEnergyVario(value / 10); bool ias_available = line.read_checked(value); fixed tas_ratio = line.read(fixed(1024)) / 1024; if (ias_available) info.ProvideBothAirspeeds(value / 10, value / 10 * tas_ratio); //hasVega = true; if (line.read_checked(value)) info.ProvidePressureAltitude(value); return true; }
static bool GPWIN(NMEAInputLine &line, NMEAInfo &info) { line.skip(2); fixed value; if (line.read_checked(value)) info.ProvidePressureAltitude(value / 10); return false; }
static bool PZAN1(NMEAInputLine &line, NMEAInfo &info) { fixed baro_altitude; if (line.read_checked(baro_altitude)) /* the ZS1 documentation does not specify wheter the altitude is STD or QNH, but Franz Poeschl confirmed via email that it is the QNH altitude */ info.ProvideBaroAltitudeTrue(baro_altitude); return true; }
/** * Parses a PTAS1 sentence * @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::PTAS1(NMEAInputLine &line, NMEA_INFO *GPS_INFO) { fixed wnet; if (line.read_checked(wnet)) { GPS_INFO->TotalEnergyVario = Units::ToSysUnit((wnet - fixed(200)) / 10, unKnots); GPS_INFO->TotalEnergyVarioAvailable = true; } line.skip(); // average vario +200 fixed baralt; bool valid_baralt = false; if (line.read_checked(baralt)) { baralt = max(fixed_zero, Units::ToSysUnit(baralt - fixed(2000), unFeet)); valid_baralt = true; GPS_INFO->BaroAltitudeAvailable = true; GPS_INFO->BaroAltitude = GPS_INFO->pressure.AltitudeToQNHAltitude(baralt); } fixed vtas; bool valid_vtas = false; if (line.read_checked(vtas)) { vtas = Units::ToSysUnit(vtas, unKnots); GPS_INFO->AirspeedAvailable = true; GPS_INFO->TrueAirspeed = vtas; } if (valid_baralt && valid_vtas) GPS_INFO->IndicatedAirspeed = vtas / GPS_INFO->pressure.AirDensityRatio(baralt); TriggerVarioUpdate(); return false; }
/** * 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, NMEA_INFO &info) { fixed value; // 0 = altitude [m] if (line.read_checked(value)) info.ProvideBaroAltitudeTrue(value); // 1 = vario [dm/s] if (line.read_checked(value)) info.ProvideTotalEnergyVario(value / 10); // 2 = airspeed [km/h] /* XXX is that TAS or IAS? */ if (line.read_checked(value)) info.ProvideTrueAirspeed(Units::ToSysUnit(value, unKiloMeterPerHour)); // 3 = netto vario [dm/s] if (line.read_checked(value)) info.ProvideNettoVario(value / 10); else /* short "$C" sentence ends after airspeed */ return true; // 4 = temperature [deg C] fixed oat; info.TemperatureAvailable = line.read_checked(oat); if (info.TemperatureAvailable) info.OutsideAirTemperature = Units::ToSysUnit(oat, unGradCelcius); // 10 = wind speed [km/h] // 11 = wind direction [degrees] SpeedVector wind; if (ReadSpeedVector(line, wind)) info.ProvideExternalWind(wind); return true; }
/** * Parses a PTAS1 sentence (Tasman Instruments proprietary). * * @param String Input string * @param params Parameter array * @param nparams Number of parameters * @param info NMEA_INFO struct to parse into * @return Parsing success */ bool NMEAParser::PTAS1(NMEAInputLine &line, NMEAInfo &info) { fixed wnet; if (line.read_checked(wnet)) info.ProvideTotalEnergyVario(Units::ToSysUnit((wnet - fixed(200)) / 10, unKnots)); line.skip(); // average vario +200 fixed baralt; if (line.read_checked(baralt)) { baralt = max(fixed_zero, Units::ToSysUnit(baralt - fixed(2000), unFeet)); info.ProvidePressureAltitude(baralt); } fixed vtas; if (line.read_checked(vtas)) info.ProvideTrueAirspeed(Units::ToSysUnit(vtas, unKnots)); return true; }
static bool GPWIN(NMEAInputLine &line, NMEA_INFO *GPS_INFO, bool enable_baro) { line.skip(2); fixed value; if (enable_baro && line.read_checked(value)) { GPS_INFO->BaroAltitude = GPS_INFO->pressure.AltitudeToQNHAltitude(value / 10); GPS_INFO->BaroAltitudeAvailable = true; } return false; }
static bool VARIO(NMEAInputLine &line, NMEA_INFO *GPS_INFO) { // $VARIO,fPressure,fVario,Bat1Volts,Bat2Volts,BatBank,TempSensor1,TempSensor2*CS fixed value; if (line.read_checked(value)) { GPS_INFO->BaroAltitude = GPS_INFO->pressure.StaticPressureToQNHAltitude(value * 100); GPS_INFO->BaroAltitudeAvailable = true; } if (line.read_checked(value)) { // vario is in dm/s GPS_INFO->TotalEnergyVario = value / 10; GPS_INFO->TotalEnergyVarioAvailable = true; } TriggerVarioUpdate(); return true; }
static bool VARIO(NMEAInputLine &line, NMEAInfo &info) { // $VARIO,fPressure,fVario,Bat1Volts,Bat2Volts,BatBank,TempSensor1,TempSensor2*CS // fVario = the variometer in decimeters per second // Bat1Volts = the voltage of the battery in bank 1 // Bat2Volts = the voltage of the battery in bank 2 // BatBank = the battery bank in use. // TempSensor1 = temperature in ºC of external wireless sensor 1 // TempSensor2 = temperature in ºC of external wireless sensor 2 fixed value; if (line.read_checked(value)) info.ProvideStaticPressure(AtmosphericPressure::HectoPascal(value)); if (line.read_checked(value)) info.ProvideTotalEnergyVario(value / 10); unsigned battery_bank; fixed voltage[2]; if (line.read_checked(voltage[0]) && line.read_checked(voltage[1]) && line.read_checked(battery_bank) && battery_bank != 0 && battery_bank <= 2) { info.voltage = voltage[battery_bank - 1]; info.voltage_available.Update(info.clock); } if (line.read_checked(value)) { info.temperature = Units::ToSysUnit(value, unGradCelcius); info.temperature_available = true; } 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; }