From 6ce9abc1c400cc0e3104755a4d44660629050587 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 13 Oct 2020 15:11:50 +0200 Subject: [PATCH 1/4] Adding flag 'is_valid' to determine if the position data within the RMC struct are valid --- extras/test/src/test_ArduinoNmeaParser.cpp | 4 ++++ src/ArduinoNmeaParser.cpp | 2 +- src/nmea/GPRMC.cpp | 10 +++++++--- src/nmea/GPRMC.h | 2 +- src/nmea/Types.h | 1 + 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/extras/test/src/test_ArduinoNmeaParser.cpp b/extras/test/src/test_ArduinoNmeaParser.cpp index 7fb0fb8..0624bb9 100644 --- a/extras/test/src/test_ArduinoNmeaParser.cpp +++ b/extras/test/src/test_ArduinoNmeaParser.cpp @@ -40,6 +40,7 @@ TEST_CASE("No NMEA message received", "[Parser-01]") ArduinoNmeaParser parser(nullptr); REQUIRE(parser.error() == ArduinoNmeaParser::Error::None); + REQUIRE(parser.rmc().is_valid == false); REQUIRE(std::isnan(parser.rmc().latitude) == true); REQUIRE(std::isnan(parser.rmc().longitude) == true); REQUIRE(parser.rmc().time_utc.hour == -1); @@ -63,6 +64,7 @@ TEST_CASE("RMC message after startup, no satellites", "[Parser-02]") encode(parser, GPRMC); REQUIRE(parser.error() == ArduinoNmeaParser::Error::None); + REQUIRE(parser.rmc().is_valid == false); REQUIRE(std::isnan(parser.rmc().latitude) == true); REQUIRE(std::isnan(parser.rmc().longitude) == true); REQUIRE(parser.rmc().time_utc.hour == -1); @@ -86,6 +88,7 @@ TEST_CASE("RMC message after startup, time fix available", "[Parser-03]") encode(parser, GPRMC); REQUIRE(parser.error() == ArduinoNmeaParser::Error::None); + REQUIRE(parser.rmc().is_valid == false); REQUIRE(std::isnan(parser.rmc().latitude) == true); REQUIRE(std::isnan(parser.rmc().longitude) == true); REQUIRE(parser.rmc().time_utc.hour == 14); @@ -108,6 +111,7 @@ TEST_CASE("Decoding starts mid-message", "[Parser-04]") encode(parser, GPRMC); + REQUIRE(parser.rmc().is_valid == true); REQUIRE(parser.rmc().latitude == Approx(52.514467)); REQUIRE(parser.rmc().longitude == Approx(13.349300)); REQUIRE(parser.rmc().speed == Approx(39.6122)); diff --git a/src/ArduinoNmeaParser.cpp b/src/ArduinoNmeaParser.cpp index 7429b52..cf8709c 100644 --- a/src/ArduinoNmeaParser.cpp +++ b/src/ArduinoNmeaParser.cpp @@ -25,7 +25,7 @@ ArduinoNmeaParser::ArduinoNmeaParser(OnRMCUpdateFunc on_rmc_update) : _error{Error::None} , _parser_state{ParserState::Synching} , _parser_buf{{0}, 0} -, _rmc{NAN, NAN, NAN, NAN, NAN, {-1, -1, -1, -1}, {-1, -1, -1}} +, _rmc{false, NAN, NAN, NAN, NAN, NAN, {-1, -1, -1, -1}, {-1, -1, -1}} , _on_rmc_update{on_rmc_update} { diff --git a/src/nmea/GPRMC.cpp b/src/nmea/GPRMC.cpp index 20c5985..ea5b386 100644 --- a/src/nmea/GPRMC.cpp +++ b/src/nmea/GPRMC.cpp @@ -61,7 +61,7 @@ bool GPRMC::parse(char const * gprmc, RmcData & data) { case ParserState::MessadeId: next_state = handle_MessadeId (token); break; case ParserState::UTCPositionFix: next_state = handle_UTCPositionFix (token, data.time_utc); break; - case ParserState::Status: next_state = handle_Status (token); break; + case ParserState::Status: next_state = handle_Status (token, data.is_valid); break; case ParserState::LatitudeVal: next_state = handle_LatitudeVal (token, data.latitude); break; case ParserState::LatitudeNS: next_state = handle_LatitudeNS (token, data.latitude); break; case ParserState::LongitudeVal: next_state = handle_LongitudeVal (token, data.longitude); break; @@ -109,13 +109,17 @@ GPRMC::ParserState GPRMC::handle_UTCPositionFix(char const * token, Time & time_ return ParserState::Status; } -GPRMC::ParserState GPRMC::handle_Status(char const * token) +GPRMC::ParserState GPRMC::handle_Status(char const * token, bool & is_valid) { + is_valid = false; + if (strlen(token) == 0) return ParserState::Error; - if(!strncmp(token, "A", 1)) + if(!strncmp(token, "A", 1)) { + is_valid = true; return ParserState::LatitudeVal; + } if(!strncmp(token, "V", 1)) return ParserState::Done; diff --git a/src/nmea/GPRMC.h b/src/nmea/GPRMC.h index ecf0795..7eccadd 100644 --- a/src/nmea/GPRMC.h +++ b/src/nmea/GPRMC.h @@ -62,7 +62,7 @@ class GPRMC static ParserState handle_MessadeId (char const * token); static ParserState handle_UTCPositionFix (char const * token, Time & time_utc); - static ParserState handle_Status (char const * token); + static ParserState handle_Status (char const * token, bool & is_valid); static ParserState handle_LatitudeVal (char const * token, float & latitude); static ParserState handle_LatitudeNS (char const * token, float & latitude); static ParserState handle_LongitudeVal (char const * token, float & longitude); diff --git a/src/nmea/Types.h b/src/nmea/Types.h index e5b957d..9171e50 100644 --- a/src/nmea/Types.h +++ b/src/nmea/Types.h @@ -36,6 +36,7 @@ typedef struct typedef struct { + bool is_valid; float latitude; float longitude; float speed; From c1932392505a71cdcb90674cb2853894f862152c Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 13 Oct 2020 15:15:43 +0200 Subject: [PATCH 2/4] Adjusting function signature of callback function to allow transfer of all data parsed from a GPRMC message --- examples/NMEA-Basic/NMEA-Basic.ino | 33 ++++++++++++++++-------------- src/ArduinoNmeaParser.cpp | 2 +- src/ArduinoNmeaParser.h | 2 +- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/examples/NMEA-Basic/NMEA-Basic.ino b/examples/NMEA-Basic/NMEA-Basic.ino index 2954bb2..f82b8bb 100644 --- a/examples/NMEA-Basic/NMEA-Basic.ino +++ b/examples/NMEA-Basic/NMEA-Basic.ino @@ -24,7 +24,7 @@ * FUNCTION DECLARATION **************************************************************************************/ -void onPositionUpdate(nmea::Time const &, float const latitude, float const longitude, float const speed, float const course); +void onPositionUpdate(nmea::RmcData const); /************************************************************************************** * GLOBAL VARIABLES @@ -53,25 +53,28 @@ void loop() * FUNCTION DEFINITION **************************************************************************************/ -void onPositionUpdate(nmea::Time const & time, float const latitude, float const longitude, float const speed, float const course) +void onPositionUpdate(nmea::RmcData const rmc) { - Serial.print(time.hour); + Serial.print(rmc.time_utc.hour); Serial.print(":"); - Serial.print(time.minute); + Serial.print(rmc.time_utc.minute); Serial.print(":"); - Serial.print(time.second); + Serial.print(rmc.time_utc.second); Serial.print("."); - Serial.print(time.microsecond); + Serial.print(rmc.time_utc.microsecond); - Serial.print(" : LON "); - Serial.print(longitude); - Serial.print(" ° | LAT "); - Serial.print(latitude); - Serial.print(" ° | VEL "); - Serial.print(speed); - Serial.print(" m/s | HEADING "); - Serial.print(course); - Serial.print(" °"); + if (rmc.is_valid) + { + Serial.print(" : LON "); + Serial.print(rmc.longitude); + Serial.print(" ° | LAT "); + Serial.print(rmc.latitude); + Serial.print(" ° | VEL "); + Serial.print(rmc.speed); + Serial.print(" m/s | HEADING "); + Serial.print(rmc.course); + Serial.print(" °"); + } Serial.println(); } diff --git a/src/ArduinoNmeaParser.cpp b/src/ArduinoNmeaParser.cpp index cf8709c..936d536 100644 --- a/src/ArduinoNmeaParser.cpp +++ b/src/ArduinoNmeaParser.cpp @@ -123,6 +123,6 @@ void ArduinoNmeaParser::parseGPRMC() _error = Error::RMC; else { if (_on_rmc_update) - _on_rmc_update(_rmc.time_utc, _rmc.latitude, _rmc.longitude, _rmc.speed, _rmc.course); + _on_rmc_update(_rmc); } } diff --git a/src/ArduinoNmeaParser.h b/src/ArduinoNmeaParser.h index 1fe3486..f597e47 100644 --- a/src/ArduinoNmeaParser.h +++ b/src/ArduinoNmeaParser.h @@ -25,7 +25,7 @@ * TYPEDEF **************************************************************************************/ -typedef std::function OnRMCUpdateFunc; +typedef std::function OnRMCUpdateFunc; /************************************************************************************** * CLASS DECLARATION From a2c1d2a5d4224a9867b3ea1e461560dbc3529f8f Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 13 Oct 2020 15:17:13 +0200 Subject: [PATCH 3/4] Renaming all functions for better consistency --- examples/NMEA-Basic/NMEA-Basic.ino | 6 +++--- src/ArduinoNmeaParser.cpp | 8 ++++---- src/ArduinoNmeaParser.h | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/NMEA-Basic/NMEA-Basic.ino b/examples/NMEA-Basic/NMEA-Basic.ino index f82b8bb..86ae557 100644 --- a/examples/NMEA-Basic/NMEA-Basic.ino +++ b/examples/NMEA-Basic/NMEA-Basic.ino @@ -24,13 +24,13 @@ * FUNCTION DECLARATION **************************************************************************************/ -void onPositionUpdate(nmea::RmcData const); +void onGprmcUpdate(nmea::RmcData const); /************************************************************************************** * GLOBAL VARIABLES **************************************************************************************/ -ArduinoNmeaParser parser(onPositionUpdate); +ArduinoNmeaParser parser(onGprmcUpdate); /************************************************************************************** * SETUP/LOOP @@ -53,7 +53,7 @@ void loop() * FUNCTION DEFINITION **************************************************************************************/ -void onPositionUpdate(nmea::RmcData const rmc) +void onGprmcUpdate(nmea::RmcData const rmc) { Serial.print(rmc.time_utc.hour); Serial.print(":"); diff --git a/src/ArduinoNmeaParser.cpp b/src/ArduinoNmeaParser.cpp index 936d536..8d63857 100644 --- a/src/ArduinoNmeaParser.cpp +++ b/src/ArduinoNmeaParser.cpp @@ -21,12 +21,12 @@ * CTOR/DTOR **************************************************************************************/ -ArduinoNmeaParser::ArduinoNmeaParser(OnRMCUpdateFunc on_rmc_update) +ArduinoNmeaParser::ArduinoNmeaParser(OnGprmcUpdateFunc on_rmc_update) : _error{Error::None} , _parser_state{ParserState::Synching} , _parser_buf{{0}, 0} , _rmc{false, NAN, NAN, NAN, NAN, NAN, {-1, -1, -1, -1}, {-1, -1, -1}} -, _on_rmc_update{on_rmc_update} +, _on_gprmc_update{on_rmc_update} { } @@ -122,7 +122,7 @@ void ArduinoNmeaParser::parseGPRMC() if (!nmea::GPRMC::parse(_parser_buf.buf, _rmc)) _error = Error::RMC; else { - if (_on_rmc_update) - _on_rmc_update(_rmc); + if (_on_gprmc_update) + _on_gprmc_update(_rmc); } } diff --git a/src/ArduinoNmeaParser.h b/src/ArduinoNmeaParser.h index f597e47..a70e4ec 100644 --- a/src/ArduinoNmeaParser.h +++ b/src/ArduinoNmeaParser.h @@ -25,7 +25,7 @@ * TYPEDEF **************************************************************************************/ -typedef std::function OnRMCUpdateFunc; +typedef std::function OnGprmcUpdateFunc; /************************************************************************************** * CLASS DECLARATION @@ -36,7 +36,7 @@ class ArduinoNmeaParser public: - ArduinoNmeaParser(OnRMCUpdateFunc on_rmc_update); + ArduinoNmeaParser(OnGprmcUpdateFunc on_rmc_update); void encode(char const c); @@ -70,7 +70,7 @@ class ArduinoNmeaParser ParserState _parser_state; ParserBuffer _parser_buf; nmea::RmcData _rmc; - OnRMCUpdateFunc _on_rmc_update; + OnGprmcUpdateFunc _on_gprmc_update; bool isParseBufferFull(); void addToParserBuffer(char const c); From a714676919024b52107faf269185293d17fb9d34 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 13 Oct 2020 15:18:03 +0200 Subject: [PATCH 4/4] Update README to show latest example code --- README.md | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index feeab5a..e694026 100644 --- a/README.md +++ b/README.md @@ -17,14 +17,33 @@ Arduino library for interfacing with any GPS module and interpreting its NMEA me ```C++ #include /* ... */ -void onPositionUpdate(float const last_fix_utc_s, float const latitude, float const longitude, float const speed, float const course) +void onGprmcUpdate(nmea::RmcData const rmc) { - char msg[64] = {0}; - snprintf(msg, 64, "[%f] %f LON | %f LAT | %d m/s | %d °", last_fix_utc_s, latitude, longitude, speed, course); - Serial.println(msg); + Serial.print(rmc.time_utc.hour); + Serial.print(":"); + Serial.print(rmc.time_utc.minute); + Serial.print(":"); + Serial.print(rmc.time_utc.second); + Serial.print("."); + Serial.print(rmc.time_utc.microsecond); + + if (rmc.is_valid) + { + Serial.print(" : LON "); + Serial.print(rmc.longitude); + Serial.print(" ° | LAT "); + Serial.print(rmc.latitude); + Serial.print(" ° | VEL "); + Serial.print(rmc.speed); + Serial.print(" m/s | HEADING "); + Serial.print(rmc.course); + Serial.print(" °"); + } + + Serial.println(); } /* ... */ -ArduinoNmeaParser parser(onPositionUpdate); +ArduinoNmeaParser parser(onGprmcUpdate); /* ... */ void setup() { Serial.begin(9600);