Beispiel #1
0
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;
}
Beispiel #2
0
bool
VegaDevice::PDVSC(NMEAInputLine &line, gcc_unused NMEAInfo &info)
{
  char responsetype[10];
  line.Read(responsetype, 10);

  char name[80];
  line.Read(name, 80);

  if (StringIsEqual(name, "ERROR"))
    // ignore error responses...
    return true;

  int value = line.Read(0);

  if (StringIsEqual(name, "ToneDeadbandCruiseLow"))
    value = std::max(value, -value);
  if (StringIsEqual(name, "ToneDeadbandCirclingLow"))
    value = std::max(value, -value);

  settings.Lock();
  settings.Set(name, value);
  settings.Unlock();

  return true;
}
Beispiel #3
0
// $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;
}
Beispiel #4
0
bool
VegaDevice::PDVSC(NMEAInputLine &line, gcc_unused NMEAInfo &info)
{
  char responsetype[10];
  line.Read(responsetype, 10);

  char name[80];
  line.Read(name, 80);

  if (strcmp(name, "ERROR") == 0)
    // ignore error responses...
    return true;

  int value = line.Read(0);

  if (strcmp(name, "ToneDeadbandCruiseLow") == 0)
    value = std::max(value, -value);
  if (strcmp(name, "ToneDeadbandCirclingLow") == 0)
    value = std::max(value, -value);

  settings_mutex.Lock();
  settings[name] = value;
  settings_mutex.Unlock();

  return true;
}
Beispiel #5
0
static bool
PDAAV(NMEAInputLine &line, gcc_unused NMEAInfo &info)
{
  gcc_unused unsigned short beepfrequency = line.Read(0);
  gcc_unused unsigned short soundfrequency = line.Read(0);
  gcc_unused unsigned char soundtype = line.Read(0);

  // Temporarily commented out - function as yet undefined
  //  audio_setconfig(beepfrequency, soundfrequency, soundtype);

  return true;
}
Beispiel #6
0
void
ParsePFLAE(NMEAInputLine &line, FlarmError &error, double clock)
{
    char type[2];
    line.Read(type, ARRAY_SIZE(type));
    if (!StringIsEqual(type, "A"))
        return;

    error.severity = (FlarmError::Severity)
                     line.Read((int)FlarmError::Severity::NO_ERROR);
    error.code = (FlarmError::Code)line.ReadHex(0);

    error.available.Update(clock);
}
Beispiel #7
0
static bool
ReadFilename(NMEAInputLine &line, RecordedFlightInfo &info)
{
  line.Read(info.internal.lx.nano_filename,
            sizeof(info.internal.lx.nano_filename));
  return info.internal.lx.nano_filename[0] != 0;
}
Beispiel #8
0
// 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;
}
Beispiel #9
0
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);
}
Beispiel #10
0
  void PFLAC(NMEAInputLine &line) {
    char command[4];
    line.Read(command, ARRAY_SIZE(command));

    if (strcmp(command, "S") == 0)
      PFLAC_S(line);
    else if (strcmp(command, "R") == 0)
      PFLAC_R(line);
  }
Beispiel #11
0
/**
 * Parse the $PLXV0 sentence (LXNav V7).
 */
static bool
PLXV0(NMEAInputLine &line, DeviceSettingsMap<std::string> &settings)
{
  char name[64];
  line.Read(name, ARRAY_SIZE(name));
  if (StringIsEmpty(name))
    return true;

  char type[2];
  line.Read(type, ARRAY_SIZE(type));
  if (type[0] != 'W')
    return true;

  const auto value = line.Rest();

  settings.Lock();
  settings.Set(name, std::string(value.begin(), value.end()));
  settings.Unlock();
  return true;
}
Beispiel #12
0
void
ParsePFLAV(NMEAInputLine &line, FlarmVersion &version, fixed clock)
{
  char type[2];
  line.Read(type, ARRAY_SIZE(type));
  if (strcmp(type, "A") != 0)
    return;

  line.Read(version.hardware_version.buffer(),
            version.hardware_version.MAX_SIZE);
  version.hardware_version.CleanASCII();

  line.Read(version.software_version.buffer(),
            version.software_version.MAX_SIZE);
  version.software_version.CleanASCII();

  line.Read(version.obstacle_version.buffer(),
            version.obstacle_version.MAX_SIZE);
  version.obstacle_version.CleanASCII();

  version.available.Update(clock);
}
Beispiel #13
0
void
ParsePFLAV(NMEAInputLine &line, FlarmVersion &version, double clock)
{
    char type[2];
    line.Read(type, ARRAY_SIZE(type));
    if (!StringIsEqual(type, "A"))
        return;

    line.Read(version.hardware_version.buffer(),
              version.hardware_version.capacity());
    version.hardware_version.CleanASCII();

    line.Read(version.software_version.buffer(),
              version.software_version.capacity());
    version.software_version.CleanASCII();

    line.Read(version.obstacle_version.buffer(),
              version.obstacle_version.capacity());
    version.obstacle_version.CleanASCII();

    version.available.Update(clock);
}
Beispiel #14
0
bool
FlarmDevice::ParsePFLAC(NMEAInputLine &line)
{
  char responsetype[10];
  line.Read(responsetype, 10);

  char name[80];
  line.Read(name, 80);

  if (strcmp(name, "ERROR") == 0)
    // ignore error responses...
    return true;

  char value[256];
  line.Read(value, ARRAY_SIZE(value));

  settings.Lock();
  settings.Set(name, value);
  settings.Unlock();

  return true;
}
Beispiel #15
0
/**
 * Parse the $PLXVC sentence (LXNAV Nano).
 *
 * $PLXVC,<key>,<type>,<values>*<checksum><cr><lf>
 */
static void
PLXVC(NMEAInputLine &line, DeviceInfo &device,
      DeviceInfo &secondary_device,
      DeviceSettingsMap<std::string> &settings)
{
  char key[64];
  line.Read(key, ARRAY_SIZE(key));

  char type[2];
  line.Read(type, ARRAY_SIZE(type));
  if (StringIsEqual(key, "SET") && type[0] == 'A') {
    char name[64];
    line.Read(name, ARRAY_SIZE(name));

    const auto value = line.Rest();
    if (!StringIsEmpty(name)) {
      settings.Lock();
      settings.Set(name, std::string(value.begin(), value.end()));
      settings.Unlock();
    }
  } else if (StringIsEqual(key, "INFO") && type[0] == 'A') {
    ParseNanoInfo(line, device);
  } else if (StringIsEqual(key, "GPSINFO") && type[0] == 'A') {
    /* the LXNAV V7 (firmware >= 2.01) forwards the Nano's INFO
       sentence with the "GPS" prefix */

    char name[64];
    line.Read(name, ARRAY_SIZE(name));

    if (StringIsEqual(name, "LXWP1")) {
      LXWP1(line, secondary_device);
    } else if (StringIsEqual(name, "INFO")) {
      line.Read(type, ARRAY_SIZE(type));
      if (type[0] == 'A')
        ParseNanoInfo(line, secondary_device);
    }
  }
}
Beispiel #16
0
  void PFLAC_R(NMEAInputLine &line) {
    char name[64];
    line.Read(name, ARRAY_SIZE(name));

    auto i = settings.find(name);
    if (i == settings.end())
      return;

    const char *value = i->second.c_str();

    char buffer[512];
    snprintf(buffer, ARRAY_SIZE(buffer), "PFLAC,A,%s,%s", name, value);
    PortWriteNMEA(*port, buffer, *env);
  }
Beispiel #17
0
void
ParsePFLAE(NMEAInputLine &line, FlarmError &error, fixed clock)
{
  char type[2];
  line.Read(type, ARRAY_SIZE(type));
  if (strcmp(type, "A") != 0)
    return;

  error.severity = (FlarmError::Severity)
    line.ReadHex((long)FlarmError::Severity::NO_ERROR);
  error.code = (FlarmError::Code)line.ReadHex(0);

  error.available.Update(clock);
}
Beispiel #18
0
// $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;
}
Beispiel #19
0
  void PFLAC_S(NMEAInputLine &line) {
    char name[64];
    line.Read(name, ARRAY_SIZE(name));

    const auto value = line.Rest();
    NarrowString<256> value_buffer;
    value_buffer.SetASCII(value.begin(), value.end());

    settings[name] = value_buffer;

    char buffer[512];
    snprintf(buffer, ARRAY_SIZE(buffer), "PFLAC,A,%s,%s", name,
             value_buffer.c_str());
    PortWriteNMEA(*port, buffer, *env);
  }
Beispiel #20
0
static bool
PZAN5(NMEAInputLine &line, NMEAInfo &info)
{
  // $PZAN5,VA,MUEHL,123.4,KM,T,234*cc

  char state[3];
  line.Read(state, 3);

  if (StringIsEqual(state, "SF"))
    info.switch_state.flight_mode = SwitchState::FlightMode::CRUISE;
  else if (StringIsEqual(state, "VA"))
    info.switch_state.flight_mode = SwitchState::FlightMode::CIRCLING;
  else
    info.switch_state.flight_mode = SwitchState::FlightMode::UNKNOWN;

  return true;
}
Beispiel #21
0
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;
}
Beispiel #22
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.ReadFirstChar());

  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;
}
Beispiel #23
0
static bool
PDVDV(NMEAInputLine &line, NMEAInfo &info)
{
  fixed value;

  if (line.ReadChecked(value))
    info.ProvideTotalEnergyVario(value / 10);

  bool ias_available = line.ReadChecked(value);
  fixed tas_ratio = line.Read(fixed(1024)) / 1024;
  if (ias_available)
    info.ProvideBothAirspeeds(value / 10, value / 10 * tas_ratio);

  //hasVega = true;

  if (line.ReadChecked(value))
    info.ProvidePressureAltitude(value);

  return true;
}
Beispiel #24
0
static bool
PZAN5(NMEAInputLine &line, NMEAInfo &info)
{
  // $PZAN5,VA,MUEHL,123.4,KM,T,234*cc

  char state[3];
  line.Read(state, 3);

  if (strcmp(state, "SF") == 0) {
    info.switch_state.flight_mode = SwitchInfo::FlightMode::CRUISE;
    info.switch_state.speed_command = true;
  } else if (strcmp(state, "VA") == 0) {
    info.switch_state.flight_mode = SwitchInfo::FlightMode::CIRCLING;
    info.switch_state.speed_command = false;
  } else
    return false;

  info.switch_state_available = true;
  return true;
}
Beispiel #25
0
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;
}
Beispiel #26
0
static bool
ParsePITV5(NMEAInputLine &line, NMEAInfo &info)
{
  fixed value;
  fixed norm, bearing;

  // wind speed [m/s]
  bool norm_valid = line.ReadChecked(norm);
  // wind dir [degrees]
  bool bearing_valid = line.ReadChecked(bearing);
  if (norm_valid && bearing_valid) {
    SpeedVector wind(Angle::Degrees(bearing), norm);
    info.ProvideExternalWind(wind);
  }

  if (line.ReadChecked(value)) {
    // sqrt density ratio
  }
  if (line.ReadChecked(value)) {
    // turbulence
  }

  // climb/cruise switch
  switch (line.Read(-1)) {
  case 1:
    info.switch_state.flight_mode = SwitchState::FlightMode::CRUISE;
    break;
  case 0:
    info.switch_state.flight_mode = SwitchState::FlightMode::CIRCLING;
    break;
  }

  // mc value [m/s]
  if (line.ReadChecked(value)) {
    info.settings.ProvideMacCready(value, info.clock);
  }

  return true;
}
Beispiel #27
0
bool
NMEAParser::ReadDate(NMEAInputLine &line, BrokenDate &date)
{
  char buffer[9];
  line.Read(buffer, 9);

  if (strlen(buffer) != 6)
    return false;

  BrokenDate new_value;
  new_value.year = atoi(buffer + 4) + 2000;
  buffer[4] = '\0';
  new_value.month = atoi(buffer + 2);
  buffer[2] = '\0';
  new_value.day = atoi(buffer);

  if (!new_value.Plausible())
    return false;

  date = new_value;
  return true;
}
Beispiel #28
0
/**
 * Parses an angle in the form "DDDMM.SSS".  Minutes are 0..59, and
 * seconds are 0..999.
 */
static bool
ReadGeoAngle(NMEAInputLine &line, Angle &a)
{
    char buffer[32], *endptr;
    line.Read(buffer, sizeof(buffer));

    char *dot = strchr(buffer, '.');
    if (dot < buffer + 3)
        return false;

    double x = strtod(dot - 2, &endptr);
    if (x < 0 || x >= 60 || *endptr != 0)
        return false;

    dot[-2] = 0;
    long y = strtol(buffer, &endptr, 10);
    if (y < 0 || y > 180 || endptr == buffer || *endptr != 0)
        return false;

    a = Angle::Degrees(fixed(y) + fixed(x) / 60);
    return true;
}
Beispiel #29
0
static bool
ReadTime(NMEAInputLine &line, BrokenTime &time)
{
  char buffer[10];
  line.Read(buffer, sizeof(buffer));

  char *p = buffer, *endptr;
  time.hour = strtoul(p, &endptr, 10);
  if (endptr == p || *endptr != ':')
    return false;

  p = endptr + 1;
  time.minute = strtoul(p, &endptr, 10);
  if (endptr == p || *endptr != ':')
    return false;

  p = endptr + 1;
  time.second = strtoul(p, &endptr, 10);
  if (endptr == p || *endptr != 0)
    return false;

  return time.IsPlausible();
}
Beispiel #30
0
static bool
ReadDate(NMEAInputLine &line, BrokenDate &date)
{
  char buffer[16];
  line.Read(buffer, sizeof(buffer));

  char *p = buffer, *endptr;
  date.day = strtoul(p, &endptr, 10);
  if (endptr == p || *endptr != '.')
    return false;

  p = endptr + 1;
  date.month = strtoul(p, &endptr, 10);
  if (endptr == p || *endptr != '.')
    return false;

  p = endptr + 1;
  date.year = strtoul(p, &endptr, 10);
  if (endptr == p || *endptr != 0)
    return false;

  return date.IsPlausible();
}