From bf0f7d30f9c089a43b588df08ac384b5fcbdffca Mon Sep 17 00:00:00 2001 From: Kosma Moczek Date: Thu, 11 Sep 2014 15:19:11 +0200 Subject: [PATCH] [API CHANGE] minmea_check: add "strict" argument In strict mode, non-checksummed frames are discarded. --- example.c | 2 +- minmea.c | 10 +++++++--- minmea.h | 4 ++-- tests.c | 60 ++++++++++++++++++++++++++++++++++++++----------------- 4 files changed, 52 insertions(+), 24 deletions(-) diff --git a/example.c b/example.c index 26b74ce..e4eebe4 100644 --- a/example.c +++ b/example.c @@ -19,7 +19,7 @@ int main(void) char line[MINMEA_MAX_LENGTH]; while (fgets(line, sizeof(line), stdin) != NULL) { printf("%s", line); - switch (minmea_sentence_id(line)) { + switch (minmea_sentence_id(line, false)) { case MINMEA_SENTENCE_RMC: { struct minmea_sentence_rmc frame; if (minmea_parse_rmc(&frame, line)) { diff --git a/minmea.c b/minmea.c index 3edee45..563f497 100644 --- a/minmea.c +++ b/minmea.c @@ -26,7 +26,7 @@ static int hex2int(char c) return -1; } -bool minmea_check(const char *sentence) +bool minmea_check(const char *sentence, bool strict) { uint8_t checksum = 0x00; @@ -42,6 +42,7 @@ bool minmea_check(const char *sentence) while (*sentence && *sentence != '*' && isprint((unsigned char) *sentence)) checksum ^= *sentence++; + // If checksum is present... if (*sentence == '*') { // Extract checksum. sentence++; @@ -56,6 +57,9 @@ bool minmea_check(const char *sentence) // Check for checksum mismatch. if (checksum != expected) return false; + } else if (strict) { + // Discard non-checksummed frames in strict mode. + return false; } // The only stuff allowed at this point is a newline. @@ -323,9 +327,9 @@ bool minmea_talker_id(char talker[3], const char *sentence) return true; } -enum minmea_sentence_id minmea_sentence_id(const char *sentence) +enum minmea_sentence_id minmea_sentence_id(const char *sentence, bool strict) { - if (!minmea_check(sentence)) + if (!minmea_check(sentence, strict)) return MINMEA_INVALID; char type[6]; diff --git a/minmea.h b/minmea.h index 2f8924a..ae8a37f 100644 --- a/minmea.h +++ b/minmea.h @@ -141,7 +141,7 @@ struct minmea_sentence_gsv { /** * Check sentence validity and checksum. Returns true for valid sentences. */ -bool minmea_check(const char *sentence); +bool minmea_check(const char *sentence, bool strict); /** * Determine talker identifier. @@ -151,7 +151,7 @@ bool minmea_talker_id(char talker[3], const char *sentence); /** * Determine sentence identifier. */ -enum minmea_sentence_id minmea_sentence_id(const char *sentence); +enum minmea_sentence_id minmea_sentence_id(const char *sentence, bool strict); /** * Scanf-like processor for NMEA sentences. Supports the following formats: diff --git a/tests.c b/tests.c index a5b00a2..6476a36 100644 --- a/tests.c +++ b/tests.c @@ -16,8 +16,11 @@ #include "minmea.h" -static const char *valid_sequences[] = { +static const char *valid_sequences_nochecksum[] = { "$GPTXT,xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", +}; + +static const char *valid_sequences_checksum[] = { "$GPTXT,01,01,02,ANTSTATUS=INIT*25", "$GPRMC,,V,,,,,,,,,,N*53", "$GPVTG,,,,,,,,,N*30", @@ -55,11 +58,20 @@ static const char *invalid_sequences[] = { START_TEST(test_minmea_check) { - for (const char **sequence=valid_sequences; *sequence; sequence++) - ck_assert_msg(minmea_check(*sequence) == true, *sequence); + for (const char **sequence=valid_sequences_nochecksum; *sequence; sequence++) { + ck_assert_msg(minmea_check(*sequence, false) == true, *sequence); + ck_assert_msg(minmea_check(*sequence, true) == false, *sequence); + } - for (const char **sequence=invalid_sequences; *sequence; sequence++) - ck_assert_msg(minmea_check(*sequence) == false, *sequence); + for (const char **sequence=valid_sequences_checksum; *sequence; sequence++) { + ck_assert_msg(minmea_check(*sequence, false) == true, *sequence); + ck_assert_msg(minmea_check(*sequence, true) == true, *sequence); + } + + for (const char **sequence=invalid_sequences; *sequence; sequence++) { + ck_assert_msg(minmea_check(*sequence, false) == false, *sequence); + ck_assert_msg(minmea_check(*sequence, true) == false, *sequence); + } } END_TEST @@ -450,7 +462,8 @@ START_TEST(test_minmea_parse_rmc1) .date = { 13, 9, 98 }, .variation = { 113, 10 }, }; - ck_assert(minmea_check(sentence) == true); + ck_assert(minmea_check(sentence, false) == true); + ck_assert(minmea_check(sentence, true) == false); ck_assert(minmea_parse_rmc(&frame, sentence) == true); ck_assert(!memcmp(&frame, &expected, sizeof(frame))); } @@ -467,7 +480,8 @@ START_TEST(test_minmea_parse_rmc2) .longitude = { -1450736, 100 }, .date = { -1, -1, -1 }, }; - ck_assert(minmea_check(sentence) == true); + ck_assert(minmea_check(sentence, false) == true); + ck_assert(minmea_check(sentence, true) == false); ck_assert(minmea_parse_rmc(&frame, sentence) == true); ck_assert(!memcmp(&frame, &expected, sizeof(frame))); } @@ -490,7 +504,8 @@ START_TEST(test_minmea_parse_gga1) .height_units = 'M', .dgps_age = 0, }; - ck_assert(minmea_check(sentence) == true); + ck_assert(minmea_check(sentence, false) == true); + ck_assert(minmea_check(sentence, true) == true); ck_assert(minmea_parse_gga(&frame, sentence) == true); ck_assert(!memcmp(&frame, &expected, sizeof(frame))); } @@ -510,7 +525,8 @@ START_TEST(test_minmea_parse_gst1) .longitude_error_deviation = { 56, 10 }, .altitude_error_deviation = { 220, 10 }, }; - ck_assert(minmea_check(sentence) == true); + ck_assert(minmea_check(sentence, false) == true); + ck_assert(minmea_check(sentence, true) == true); ck_assert(minmea_parse_gst(&frame, sentence) == true); ck_assert(!memcmp(&frame, &expected, sizeof(frame))); } @@ -528,7 +544,8 @@ START_TEST(test_minmea_parse_gsa1) .hdop = { 13, 10 }, .vdop = { 21, 10 }, }; - ck_assert(minmea_check(sentence) == true); + ck_assert(minmea_check(sentence, false) == true); + ck_assert(minmea_check(sentence, true) == true); ck_assert(minmea_parse_gsa(&frame, sentence) == true); ck_assert(!memcmp(&frame, &expected, sizeof(frame))); } @@ -546,7 +563,8 @@ START_TEST(test_minmea_parse_gll1) .mode = MINMEA_GLL_MODE_AUTONOMOUS, }; - ck_assert(minmea_check(sentence) == true); + ck_assert(minmea_check(sentence, false) == true); + ck_assert(minmea_check(sentence, true) == true); ck_assert(minmea_parse_gll(&frame, sentence) == true); ck_assert(!memcmp(&frame, &expected, sizeof(frame))); } @@ -564,7 +582,8 @@ START_TEST(test_minmea_parse_gll2) .mode = 0, }; - ck_assert(minmea_check(sentence) == true); + ck_assert(minmea_check(sentence, false) == true); + ck_assert(minmea_check(sentence, true) == false); ck_assert(minmea_parse_gll(&frame, sentence) == true); ck_assert(!memcmp(&frame, &expected, sizeof(frame))); } @@ -605,7 +624,8 @@ START_TEST(test_minmea_parse_gsv1) } } }; - ck_assert(minmea_check(sentence) == true); + ck_assert(minmea_check(sentence, false) == true); + ck_assert(minmea_check(sentence, true) == true); ck_assert(minmea_parse_gsv(&frame, sentence) == true); ck_assert(!memcmp(&frame, &expected, sizeof(frame))); } @@ -646,7 +666,8 @@ START_TEST(test_minmea_parse_gsv2) } } }; - ck_assert(minmea_check(sentence) == true); + ck_assert(minmea_check(sentence, false) == true); + ck_assert(minmea_check(sentence, true) == true); ck_assert(minmea_parse_gsv(&frame, sentence) == true); ck_assert(!memcmp(&frame, &expected, sizeof(frame))); } @@ -687,7 +708,8 @@ START_TEST(test_minmea_parse_gsv3) } } }; - ck_assert(minmea_check(sentence) == true); + ck_assert(minmea_check(sentence, false) == true); + ck_assert(minmea_check(sentence, true) == true); ck_assert(minmea_parse_gsv(&frame, sentence) == true); ck_assert(!memcmp(&frame, &expected, sizeof(frame))); } @@ -728,7 +750,8 @@ START_TEST(test_minmea_parse_gsv4) } } }; - ck_assert(minmea_check(sentence) == true); + ck_assert(minmea_check(sentence, false) == true); + ck_assert(minmea_check(sentence, true) == true); ck_assert(minmea_parse_gsv(&frame, sentence) == true); ck_assert(!memcmp(&frame, &expected, sizeof(frame))); } @@ -769,7 +792,8 @@ START_TEST(test_minmea_parse_gsv5) } } }; - ck_assert(minmea_check(sentence) == true); + ck_assert(minmea_check(sentence, false) == true); + ck_assert(minmea_check(sentence, true) == true); ck_assert(minmea_parse_gsv(&frame, sentence) == true); ck_assert(!memcmp(&frame, &expected, sizeof(frame))); } @@ -788,7 +812,7 @@ START_TEST(test_minmea_usage1) }; for (const char **sentence=sentences; *sentence; sentence++) { - switch (minmea_sentence_id(*sentence)) { + switch (minmea_sentence_id(*sentence, false)) { case MINMEA_SENTENCE_RMC: { struct minmea_sentence_rmc frame; ck_assert(minmea_parse_rmc(&frame, *sentence) == true);