Skip to content
This repository has been archived by the owner on May 26, 2024. It is now read-only.

Commit

Permalink
Merge pull request #25 from 107-systems/fix-early-parse-abort
Browse files Browse the repository at this point in the history
Fix early parse abort in case of missing RMC sentence entries
  • Loading branch information
aentinger authored Nov 10, 2020
2 parents 48ee402 + 25970ba commit 46cba8e
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 83 deletions.
13 changes: 1 addition & 12 deletions extras/test/src/test_ArduinoNmeaParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,18 +137,7 @@ TEST_CASE("NMEA message with data corruption (checksum mismatch) received", "[Pa
REQUIRE(parser.error() == ArduinoNmeaParser::Error::Checksum);
}

TEST_CASE("Invalid GPRMC message received", "[Parser-06]")
{
ArduinoNmeaParser parser(nullptr);

std::string const GPRMC = "$GPRMC,052852.105,A,5230.868,Y,01320.958,E,077.0,023.5,080720,000.0,W*6E\r\n";

REQUIRE(parser.error() == ArduinoNmeaParser::Error::None);
encode(parser, GPRMC);
REQUIRE(parser.error() == ArduinoNmeaParser::Error::RMC);
}

TEST_CASE("Multiple NMEA messages received", "[Parser-07]")
TEST_CASE("Multiple NMEA messages received", "[Parser-06]")
{
ArduinoNmeaParser parser(nullptr);

Expand Down
58 changes: 38 additions & 20 deletions extras/test/src/test_GxRMC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ SCENARIO("Extracting latitude/longiture from valid GPRMC message", "[GxRMC-01]")
{
std::string const GPRMC = "$GPRMC,062101.714,A,5001.869,N,01912.114,E,955535.7,116.2,290520,000.0,W*45\r\n";

REQUIRE(nmea::GxRMC::parse(GPRMC.c_str(), data) == true);
nmea::GxRMC::parse(GPRMC.c_str(), data);

REQUIRE(data.latitude == Approx(50.03114442));
REQUIRE(data.longitude == Approx(19.20189679));
}
Expand All @@ -42,7 +43,8 @@ SCENARIO("Extracting latitude/longiture from valid GPRMC message", "[GxRMC-01]")
{
std::string const GPRMC = "$GPRMC,122311.239,A,4056.748,N,11212.614,W,,,290620,000.0,W*63\r\n";

REQUIRE(nmea::GxRMC::parse(GPRMC.c_str(), data) == true);
nmea::GxRMC::parse(GPRMC.c_str(), data);

REQUIRE(data.latitude == Approx(40.9458060446613));
REQUIRE(data.longitude == Approx(-112.210235595703));
}
Expand All @@ -51,7 +53,8 @@ SCENARIO("Extracting latitude/longiture from valid GPRMC message", "[GxRMC-01]")
{
std::string const GPRMC = "$GPRMC,122311.239,A,2727.069,S,05859.190,W,,,290620,000.0,W*76\r\n";

REQUIRE(nmea::GxRMC::parse(GPRMC.c_str(), data) == true);
nmea::GxRMC::parse(GPRMC.c_str(), data);

REQUIRE(data.latitude == Approx(-27.4511422937699));
REQUIRE(data.longitude == Approx(-58.986502289772));
}
Expand All @@ -60,7 +63,8 @@ SCENARIO("Extracting latitude/longiture from valid GPRMC message", "[GxRMC-01]")
{
std::string const GPRMC = "$GPRMC,122311.239,A,0610.522,S,10649.632,E,,,290620,000.0,W*6D\r\n";

REQUIRE(nmea::GxRMC::parse(GPRMC.c_str(), data) == true);
nmea::GxRMC::parse(GPRMC.c_str(), data);

REQUIRE(data.latitude == Approx(-6.17536097471491));
REQUIRE(data.longitude == Approx(106.827192306519));
}
Expand All @@ -86,7 +90,8 @@ TEST_CASE("Extracting speed over ground from valid GPRMC message", "[GxRMC-03]")
{
std::string const GPRMC = ("$GPRMC,052856.105,A,5230.874,N,01321.056,E,085.7,206.4,080720,000.0,W*78\r\n");

REQUIRE(nmea::GxRMC::parse(GPRMC.c_str(), data) == true);
nmea::GxRMC::parse(GPRMC.c_str(), data);

/* 85.7 kts ~= 44.088 m/s */
REQUIRE(data.speed == Approx(44.088f));
}
Expand All @@ -95,15 +100,17 @@ TEST_CASE("Extracting track angle from valid GPRMC message", "[GxRMC-04]")
{
std::string const GPRMC = ("$GPRMC,052856.105,A,5230.874,N,01321.056,E,085.7,206.4,080720,000.0,W*78\r\n");

REQUIRE(nmea::GxRMC::parse(GPRMC.c_str(), data) == true);
nmea::GxRMC::parse(GPRMC.c_str(), data);

REQUIRE(data.course == Approx(206.4f));
}

TEST_CASE("Extracting position time from valid GPRMC message", "[GxRMC-05]")
{
std::string const GPRMC = ("$GPRMC,052856.105,A,5230.874,N,01321.056,E,085.7,206.4,080720,000.0,W*78\r\n");

REQUIRE(nmea::GxRMC::parse(GPRMC.c_str(), data) == true);
nmea::GxRMC::parse(GPRMC.c_str(), data);

/* 052856.105 -> 05:28:56.105 -> */
REQUIRE(data.time_utc.hour == 5);
REQUIRE(data.time_utc.minute == 28);
Expand All @@ -115,7 +122,8 @@ TEST_CASE("Extracting date from valid GPRMC message", "[GxRMC-06]")
{
std::string const GPRMC = ("$GPRMC,052856.105,A,5230.874,N,01321.056,E,085.7,206.4,080720,000.0,W*78\r\n");

REQUIRE(nmea::GxRMC::parse(GPRMC.c_str(), data) == true);
nmea::GxRMC::parse(GPRMC.c_str(), data);

REQUIRE(data.date.day == 8);
REQUIRE(data.date.month == 7);
REQUIRE(data.date.year == 2020);
Expand All @@ -125,24 +133,34 @@ TEST_CASE("Extracting magnetic variation from valid GPRMC message", "[GxRMC-07]"
{
std::string const GPRMC = ("$GPRMC,052856.105,A,5230.874,N,01321.056,E,085.7,206.4,080720,000.0,W*78\r\n");

REQUIRE(nmea::GxRMC::parse(GPRMC.c_str(), data) == true);
nmea::GxRMC::parse(GPRMC.c_str(), data);

REQUIRE(data.magnetic_variation == Approx(0.0));
}

TEST_CASE("Extracted status indicates void ('V') position data", "[GxRMC-08]")
{
std::string const GPRMC = ("$GPRMC,052856.105,V,5230.874,N,01321.056,E,085.7,206.4,080720,000.0,W*78\r\n");

data.latitude = 1.0f; data.longitude = 2.0f; data.speed = 3.0f; data.course = 4.0f;
data.time_utc.hour = -1; data.time_utc.minute = -1; data.time_utc.second = -1; data.time_utc.microsecond = -1;
nmea::GxRMC::parse(GPRMC.c_str(), data);

REQUIRE(nmea::GxRMC::parse(GPRMC.c_str(), data) == true);
REQUIRE(data.latitude == 1.0f);
REQUIRE(data.longitude == 2.0f);
REQUIRE(data.speed == 3.0f);
REQUIRE(data.course == 4.0f);
REQUIRE(data.time_utc.hour == 5);
REQUIRE(data.time_utc.minute == 28);
REQUIRE(data.time_utc.second == 56);
REQUIRE(data.time_utc.microsecond == 105);
REQUIRE(data.is_valid == false);
}

TEST_CASE("GxRMC message contains only date and time, but no location fix yet ", "[GxRMC-09]")
{
std::string const GPRMC = ("$GPRMC,144602.00,V,,,,,,,011120,,,N*7B\r\n");

nmea::GxRMC::parse(GPRMC.c_str(), data);

/* RMC TIME = '144602.00' */
REQUIRE(data.time_utc.hour == 14);
REQUIRE(data.time_utc.minute == 46);
REQUIRE(data.time_utc.second == 02);
REQUIRE(data.time_utc.microsecond == 0);

/* RMC DATE = '011120' */
REQUIRE(data.date.day == 1);
REQUIRE(data.date.month == 11);
REQUIRE(data.date.year == 2020);
}
8 changes: 3 additions & 5 deletions src/ArduinoNmeaParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,8 @@ void ArduinoNmeaParser::terminateParserBuffer()

void ArduinoNmeaParser::parseGxRMC()
{
if (!nmea::GxRMC::parse(_parser_buf.buf, _rmc))
_error = Error::RMC;
else {
if (_on_rmc_update)
nmea::GxRMC::parse(_parser_buf.buf, _rmc);

if (_on_rmc_update)
_on_rmc_update(_rmc);
}
}
2 changes: 1 addition & 1 deletion src/ArduinoNmeaParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class ArduinoNmeaParser
inline const nmea::RmcData rmc() const { return _rmc; }


enum class Error { None, Checksum, RMC };
enum class Error { None, Checksum };

inline void clearerr() { _error = Error::None; }
inline Error error () const { return _error; }
Expand Down
54 changes: 12 additions & 42 deletions src/nmea/GxRMC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ constexpr float kts_to_m_per_s(float const v) { return (v / 1.9438444924574f); }
* PUBLIC MEMBER FUNCTIONS
**************************************************************************************/

bool GxRMC::parse(char const * gprmc, RmcData & data)
void GxRMC::parse(char const * gprmc, RmcData & data)
{
ParserState state = ParserState::MessadeId;

Expand Down Expand Up @@ -68,14 +68,11 @@ bool GxRMC::parse(char const * gprmc, RmcData & data)
case ParserState::MagneticVariation: next_state = handle_MagneticVariation (token, data.magnetic_variation); break;
case ParserState::MagneticVariationEastWest: next_state = handle_MagneticVariationEastWest(token, data.magnetic_variation); break;
case ParserState::Checksum: next_state = handle_Checksum (token); break;
case ParserState::Done: return true; break;
case ParserState::Error: return false; break;
case ParserState::Done: break;
};

state = next_state;
}

return (state == ParserState::Done);
}

/**************************************************************************************
Expand All @@ -84,9 +81,6 @@ bool GxRMC::parse(char const * gprmc, RmcData & data)

GxRMC::ParserState GxRMC::handle_MessadeId(char const * token, RmcSource & source)
{
if (!util::rmc_isGxRMC(token))
return ParserState::Error;

if (util::rmc_isGPRMC(token))
source = RmcSource::GPS;
else if (util::rmc_isGLRMC(token))
Expand Down Expand Up @@ -116,20 +110,12 @@ GxRMC::ParserState GxRMC::handle_UTCPositionFix(char const * token, Time & time_

GxRMC::ParserState GxRMC::handle_Status(char const * token, bool & is_valid)
{
is_valid = false;

if (strlen(token) == 0)
return ParserState::Error;

if(!strncmp(token, "A", 1)) {
if(strlen(token) > 0 && !strncmp(token, "A", 1))
is_valid = true;
return ParserState::LatitudeVal;
}

if(!strncmp(token, "V", 1))
return ParserState::Done;
else
is_valid = false;

return ParserState::Error;
return ParserState::LatitudeVal;
}

GxRMC::ParserState GxRMC::handle_LatitudeVal(char const * token, float & latitude)
Expand All @@ -144,18 +130,10 @@ GxRMC::ParserState GxRMC::handle_LatitudeVal(char const * token, float & latitud

GxRMC::ParserState GxRMC::handle_LatitudeNS(char const * token, float & latitude)
{
if (strlen(token))
{
if(!strncmp(token, "N", 1))
return ParserState::LongitudeVal;

if(!strncmp(token, "S", 1)) {
latitude *= (-1.0f);
return ParserState::LongitudeVal;
}
}
if (strlen(token) > 0 && !strncmp(token, "S", 1))
latitude *= (-1.0f);

return ParserState::Error;
return ParserState::LongitudeVal;
}

GxRMC::ParserState GxRMC::handle_LongitudeVal(char const * token, float & longitude)
Expand All @@ -170,18 +148,10 @@ GxRMC::ParserState GxRMC::handle_LongitudeVal(char const * token, float & longit

GxRMC::ParserState GxRMC::handle_LongitudeEW(char const * token, float & longitude)
{
if (strlen(token))
{
if(!strncmp(token, "E", 1))
return ParserState::SpeedOverGround;

if(!strncmp(token, "W", 1)) {
longitude *= (-1.0f);
return ParserState::SpeedOverGround;
}
}
if (strlen(token) > 0 && !strncmp(token, "W", 1))
longitude *= (-1.0f);

return ParserState::Error;
return ParserState::SpeedOverGround;
}

GxRMC::ParserState GxRMC::handle_SpeedOverGround(char const * token, float & speed)
Expand Down
5 changes: 2 additions & 3 deletions src/nmea/GxRMC.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class GxRMC

public:

static bool parse(char const * gprmc, RmcData & data);
static void parse(char const * gprmc, RmcData & data);

private:

Expand All @@ -54,8 +54,7 @@ class GxRMC
MagneticVariation,
MagneticVariationEastWest,
Checksum,
Done,
Error
Done
};

static ParserState handle_MessadeId (char const * token, RmcSource & source);
Expand Down

0 comments on commit 46cba8e

Please sign in to comment.