コード例 #1
0
ファイル: Parser.cpp プロジェクト: macsux/XCSoar
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;
}
コード例 #2
0
ファイル: EWMicroRecorder.cpp プロジェクト: hnpilot/XCSoar
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;
}
コード例 #3
0
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;
}
コード例 #4
0
ファイル: Parser.cpp プロジェクト: Plantain/XCSoar
/**
 * 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;
}
コード例 #5
0
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;
}
コード例 #6
0
/**
 * 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;
}