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; }
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; }
// $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; }
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; }
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; }
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); }
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; }
// 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; }
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); }
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); }
/** * 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; }
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); }
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); }
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; }
/** * 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); } } }
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); }
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); }
// $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; }
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); }
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; }
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; }
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; }
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; }
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; }
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 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; }
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; }
/** * 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; }
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(); }
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(); }