/** * 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, NMEA_INFO &info) { fixed value; // 0,1 = GPS altitude, unit if (line.read_checked_compare(info.GPSAltitude, "M")) info.GPSAltitudeAvailable.Update(info.clock); // 2,3 = baro altitude, unit if (line.read_checked_compare(value, "M")) info.ProvideBaroAltitudeTrue(value); // 4-7 = integrated vario, unit line.skip(4); // 8,9 = indicated or true airspeed, unit if (line.read_checked_compare(value, "KH")) // XXX is that TAS or IAS? Documentation isn't clear. info.ProvideBothAirspeeds(Units::ToSysUnit(value, unKiloMeterPerHour)); // 10,11 = temperature, unit info.TemperatureAvailable = line.read_checked_compare(value, "C"); if (info.TemperatureAvailable) info.OutsideAirTemperature = Units::ToSysUnit(value, unGradCelcius); return true; }
/** * Update the measurements if new level reached * @param basic NMEA_INFO for temperature and humidity */ void CuSonde::updateMeasurements(const NMEA_INFO &basic) { // if (not flying) nothing to update... if (!basic.flight.Flying) return; // if (no temperature or humidity available) nothing to update... if (!basic.TemperatureAvailable || !basic.HumidityAvailable) return; // find appropriate level unsigned short level = (unsigned short)((int)max(basic.GetAltitudeBaroPreferred(), fixed(0.0)) / CUSONDE_HEIGHTSTEP); // if (level out of range) cancel update if (level >= CUSONDE_NUMLEVELS) return; // if (level skipped) cancel update if (abs(level - last_level) > 1) { last_level = level; return; } // if (no level transition yet) wait for transition if (abs(level - last_level) == 0) return; // calculate ground height hGround = basic.AltitudeAGL; // if (going up) if (level > last_level) { // we round down (level) because of potential lag of temp sensor cslevels[level].updateTemps(basic.RelativeHumidity, Units::ToUserUnit(basic.OutsideAirTemperature, unGradCelcius)); cslevels[level].updateThermalIndex(level); if (level > 0) { findThermalHeight((unsigned short)(level - 1)); findCloudBase((unsigned short)(level - 1)); } // if (going down) } else { // we round up (level+1) because of potential lag of temp sensor cslevels[level + 1].updateTemps(basic.RelativeHumidity, Units::ToUserUnit(basic.OutsideAirTemperature, unGradCelcius)); cslevels[level + 1].updateThermalIndex((unsigned short)(level + 1)); if (level < CUSONDE_NUMLEVELS - 1) { findThermalHeight(level); findCloudBase(level); } } last_level = level; }
bool EWMicroRecorderDevice::ParseNMEA(const char *String, NMEA_INFO &info) { if (!VerifyNMEAChecksum(String)) return false; NMEAInputLine line(String); char type[16]; line.read(type, 16); if (strcmp(type, "$PGRMZ") == 0) { fixed value; /* The normal Garmin $PGRMZ line contains the "true" barometric altitude above MSL (corrected with QNH), but EWMicroRecorder differs here slightly: it emits the uncorrected barometric altitude. That is the only reason why we catch this sentence in the driver instead of letting the generic class NMEAParser do it. */ if (ReadAltitude(line, value)) info.ProvidePressureAltitude(value); return true; } else return false; }
/** * 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; }
/** * 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; }
/** * Parse a "$BRSF" sentence. * * Example: "$BRSF,063,-013,-0035,1,193,00351,535,485*38" */ static bool FlytecParseBRSF(NMEAInputLine &line, NMEA_INFO &info) { fixed value; // 0 = indicated or true airspeed [km/h] if (line.read_checked(value)) // XXX is that TAS or IAS? Documentation isn't clear. info.ProvideBothAirspeeds(Units::ToSysUnit(value, unKiloMeterPerHour)); // 1 = integrated vario [dm/s] // 2 = altitude A2 [m] (XXX what's this?) // 3 = waypoint // 4 = bearing to waypoint [degrees] // 5 = distance to waypoint [100m] // 6 = MacCready speed to fly [100m/h] // 7 = speed to fly, best glide [100m/h] 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; }