bool OpenVarioDevice::POV(NMEAInputLine &line, NMEAInfo &info) { /* * Type definitions: * * E: TE vario in m/s * P: static pressure in hPa * Q: dynamic pressure in Pa * R: total pressure in hPa * S: true airspeed in km/h * T: temperature in deg C */ while (!line.IsEmpty()) { char type = line.ReadOneChar(); if (type == '\0') break; fixed value; if (!line.ReadChecked(value)) break; switch (type) { case 'E': { info.ProvideTotalEnergyVario(value); break; } case 'P': { AtmosphericPressure pressure = AtmosphericPressure::HectoPascal(value); info.ProvideStaticPressure(pressure); break; } case 'Q': { AtmosphericPressure pressure = AtmosphericPressure::Pascal(value); info.ProvideDynamicPressure(pressure); break; } case 'R': { AtmosphericPressure pressure = AtmosphericPressure::HectoPascal(value); info.ProvidePitotPressure(pressure); break; } case 'S': { value = Units::ToSysUnit(value, Unit::KILOMETER_PER_HOUR); info.ProvideTrueAirspeed(value); break; } case 'T': { info.temperature = CelsiusToKelvin(value); info.temperature_available = true; break; } } } return true; }
static bool ParsePITV4(NMEAInputLine &line, NMEAInfo &info) { fixed value; // TE vario [m/s] if (line.ReadChecked(value)) info.ProvideTotalEnergyVario(value); return true; }
static bool PZAN2(NMEAInputLine &line, NMEAInfo &info) { fixed vtas, wnet; if (line.ReadChecked(vtas)) info.ProvideTrueAirspeed(Units::ToSysUnit(vtas, Unit::KILOMETER_PER_HOUR)); if (line.ReadChecked(wnet)) info.ProvideTotalEnergyVario((wnet - fixed(10000)) / 100); 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; }
/** * $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; }
/** * $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, k; line.skip(); /* device */ if (line.read_checked(i)) info.ProvideTotalEnergyVario(fixed(i) / 10); line.skip(); /* average vario */ if (line.read_checked(i)) info.ProvideNettoVario(fixed(i) / 10); line.skip(); /* average netto vario */ line.skip(); /* speed to fly */ if (line.read_checked(i)) info.ProvidePressureAltitude(fixed(i)); if (line.read_checked(i)) info.ProvideBaroAltitudeTrue(fixed(i)); bool have_ias = line.read_checked(i); bool have_tas = line.read_checked(k); if (have_ias && have_tas) info.ProvideBothAirspeeds(Units::ToSysUnit(fixed(i) / 10, Unit::KILOMETER_PER_HOUR), Units::ToSysUnit(fixed(k) / 10, Unit::KILOMETER_PER_HOUR)); else if (!have_ias && have_tas) info.ProvideTrueAirspeed(Units::ToSysUnit(fixed(k) / 10, Unit::KILOMETER_PER_HOUR)); if (line.read_checked(i)) { info.voltage = fixed(i) / 10; info.voltage_available.Update(info.clock); } if (line.read_checked(i)) { info.temperature = CelsiusToKelvin(fixed(i) / 10); info.temperature_available = 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; }
/** * 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) { double value; // 0 = vario [dm/s] if (line.ReadChecked(value)) info.ProvideTotalEnergyVario(value / 10); if (line.Rest().empty()) /* short "$D" sentence ends after vario */ return true; // 1 = air pressure [Pa] if (line.ReadChecked(value)) info.ProvideStaticPressure(AtmosphericPressure::Pascal(value)); // 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] double 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; }
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; }
/** * 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; }
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; }
/** * $PWES0,DD,VVVV,MMMM,NNNN,BBBB,SSSS,AAAAA,QQQQQ,IIII,TTTT,UUU,CCC*CS<CR><LF> */ static bool PWES0(NMEAInputLine &line, NMEAInfo &info) { int i, k; line.skip(); /* device */ if (line.read_checked(i)) info.ProvideTotalEnergyVario(fixed(i) / 10); line.skip(); /* average vario */ if (line.read_checked(i)) info.ProvideNettoVario(fixed(i) / 10); line.skip(); /* average netto vario */ line.skip(); /* speed to fly */ if (line.read_checked(i)) info.ProvidePressureAltitude(fixed(i)); if (line.read_checked(i)) info.ProvideBaroAltitudeTrue(fixed(i)); bool have_ias = line.read_checked(i); bool have_tas = line.read_checked(k); if (have_ias && have_tas) info.ProvideBothAirspeeds(Units::ToSysUnit(fixed(i) / 10, unKiloMeterPerHour), Units::ToSysUnit(fixed(k) / 10, unKiloMeterPerHour)); if (line.read_checked(i)) { info.voltage = fixed(i) / 10; info.voltage_available.Update(info.clock); } if (line.read_checked(i)) { info.temperature = Units::ToSysUnit(fixed(i) / 10, unGradCelcius); info.temperature_available = true; } 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 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; }
/** * 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; }
/* !w,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>,<13>*hh<CR><LF> <1> Vector wind direction in degrees <2> Vector wind speed in 10ths of meters per second <3> Vector wind age in seconds <4> Component wind in 10ths of Meters per second + 500 (500 = 0, 495 = 0.5 m/s tailwind) <5> True altitude in Meters + 1000 <6> Instrument QNH setting <7> True airspeed in 100ths of Meters per second <8> Variometer reading in 10ths of knots + 200 <9> Averager reading in 10ths of knots + 200 <10> Relative variometer reading in 10ths of knots + 200 <11> Instrument MacCready setting in 10ths of knots <12> Instrument Ballast setting in percent of capacity <13> Instrument Bug setting *hh Checksum, XOR of all bytes */ static bool cai_w(NMEAInputLine &line, NMEAInfo &info) { SpeedVector wind; if (ReadSpeedVector(line, wind)) info.ProvideExternalWind(wind.Reciprocal()); line.skip(2); fixed value; if (line.read_checked(value)) info.ProvideBaroAltitudeTrue(value - fixed(1000)); if (line.read_checked(value)) info.settings.ProvideQNH(value, info.clock); if (line.read_checked(value)) info.ProvideTrueAirspeed(value / 100); if (line.read_checked(value)) info.ProvideTotalEnergyVario(Units::ToSysUnit((value - fixed(200)) / 10, unKnots)); line.skip(2); int i; if (line.read_checked(i)) info.settings.ProvideMacCready(Units::ToSysUnit(fixed(i) / 10, unKnots), info.clock); if (line.read_checked(i)) info.settings.ProvideBallastFraction(fixed(i) / 100, info.clock); if (line.read_checked(i)) info.settings.ProvideBugs(fixed(i) / 100, info.clock); return true; }
static bool PDVDV(NMEAInputLine &line, NMEAInfo &info) { int value; if (line.ReadChecked(value)) info.ProvideTotalEnergyVario(fixed(value) / 10); bool ias_available = line.ReadChecked(value); int tas_ratio = line.Read(1024); if (ias_available) { const fixed ias = fixed(value) / 10; info.ProvideBothAirspeeds(ias, ias * tas_ratio / 1024); } //hasVega = true; if (line.ReadChecked(value)) info.ProvidePressureAltitude(fixed(value)); 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; }
/** * Parse a "$PILC,PDA1" sentence. * * Example: "$PILC,PDA1,1489,-3.21,274,15,58*7D" */ static bool ParsePDA1(NMEAInputLine &line, NMEAInfo &info) { fixed value; // altitude [m] int altitude; if (line.ReadChecked(altitude)) info.ProvideBaroAltitudeTrue(fixed(altitude)); // total energy vario [m/s] if (line.ReadChecked(value)) info.ProvideTotalEnergyVario(value); // wind direction [degrees, kph] SpeedVector wind; if (ReadSpeedVector(line, wind)) info.ProvideExternalWind(wind); // confidence [0..100] // not used return true; }
/** * 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; }