From d973b98d66689906b3a1cb4f9ad62eb18fb3a0bd Mon Sep 17 00:00:00 2001 From: Kosma Moczek Date: Mon, 24 Mar 2014 22:40:25 +0100 Subject: [PATCH] minmea: don't include talker id in sentence type. This is a backwards-incompatible change that I knew I'd have to introduce sooner or later. Which means now. Long story short: when I first started writing this library, I wanted to make things simpler by treating the entire talker+sentence as one big ID. Of course, this is an oversimplification, as there are different talkers out there. Turns out they're more common than I initially thought. I just came across a module (read: I had one soldered to my board by our crazy hardware guy) that spits out GPRMC, GLRMC or GNRMC depending on where it got the data. I could have kludged around this, but here's this change, for the purity of code. Fortunately, we're the only users of this codebase as far as I know, so no real harm is done - but it's a lesson to design my interfaces right from the very start so I don't have to break compatibility and write apologetic messages later on. --- README.md | 17 +++++++--------- example.c | 14 ++++++------- minmea.c | 28 +++++++++++++------------- minmea.h | 32 ++++++++++++++--------------- tests.c | 60 +++++++++++++++++++++++++++---------------------------- 5 files changed, 74 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index e87e244..cc6adb7 100644 --- a/README.md +++ b/README.md @@ -53,10 +53,10 @@ The library doesn't perform this conversion automatically for the following reas char line[MINMEA_MAX_LENGTH]; while (fgets(line, sizeof(line), stdin) != NULL) { printf("%s", line); - switch (minmea_type(line)) { - case MINMEA_GPRMC: { - struct minmea_gprmc frame; - if (minmea_parse_gprmc(&frame, line)) { + switch (minmea_sentence_id(line)) { + case MINMEA_SENTENCE_RMC: { + struct minmea_sentence_rmc frame; + if (minmea_parse_rmc(&frame, line)) { printf("+++ raw coordinates and speed: (%d/%d,%d/%d) %d/%d\n", frame.latitude, frame.latitude_scale, frame.longitude, frame.longitude_scale, @@ -72,15 +72,12 @@ The library doesn't perform this conversion automatically for the following reas } } break; - case MINMEA_GPGGA: { - struct minmea_gpgga frame; - if (minmea_parse_gpgga(&frame, line)) { + case MINMEA_SENTENCE_GGA: { + struct minmea_sentence_gga frame; + if (minmea_parse_gga(&frame, line)) { printf("$GPGGA: fix quality: %d\n", frame.fix_quality); } } break; - - default: { - } break; } } ``` diff --git a/example.c b/example.c index 0e10607..e973814 100644 --- a/example.c +++ b/example.c @@ -17,10 +17,10 @@ int main() char line[MINMEA_MAX_LENGTH]; while (fgets(line, sizeof(line), stdin) != NULL) { printf("%s", line); - switch (minmea_type(line)) { - case MINMEA_GPRMC: { - struct minmea_gprmc frame; - if (minmea_parse_gprmc(&frame, line)) { + switch (minmea_sentence_id(line)) { + case MINMEA_SENTENCE_RMC: { + struct minmea_sentence_rmc frame; + if (minmea_parse_rmc(&frame, line)) { printf("+++ raw coordinates and speed: (%d/%d,%d/%d) %d/%d\n", frame.latitude, frame.latitude_scale, frame.longitude, frame.longitude_scale, @@ -36,9 +36,9 @@ int main() } } break; - case MINMEA_GPGGA: { - struct minmea_gpgga frame; - if (minmea_parse_gpgga(&frame, line)) { + case MINMEA_SENTENCE_GGA: { + struct minmea_sentence_gga frame; + if (minmea_parse_gga(&frame, line)) { printf("$GPGGA: fix quality: %d\n", frame.fix_quality); } } break; diff --git a/minmea.c b/minmea.c index 7ff87b5..1530be6 100644 --- a/minmea.c +++ b/minmea.c @@ -175,7 +175,7 @@ bool minmea_scan(const char *sentence, const char *format, ...) *buf = '\0'; } break; - case 't': { // NMEA talker+sequence identifier (char *). + case 't': { // NMEA talker+sentence identifier (char *). if (field[0] != '$') goto end; for (int i=0; i<5; i++) @@ -259,7 +259,7 @@ end: return result; } -enum minmea_type minmea_type(const char *sentence) +enum minmea_sentence_id minmea_sentence_id(const char *sentence) { if (!minmea_check(sentence)) return MINMEA_INVALID; @@ -268,17 +268,17 @@ enum minmea_type minmea_type(const char *sentence) if (!minmea_scan(sentence, "t", type)) return MINMEA_INVALID; - if (!strcmp(type, "GPRMC")) - return MINMEA_GPRMC; - if (!strcmp(type, "GPGGA")) - return MINMEA_GPGGA; - if (!strcmp(type, "GPGSA")) - return MINMEA_GPGSA; + if (!strcmp(type+2, "RMC")) + return MINMEA_SENTENCE_RMC; + if (!strcmp(type+2, "GGA")) + return MINMEA_SENTENCE_GGA; + if (!strcmp(type+2, "GSA")) + return MINMEA_SENTENCE_GSA; return MINMEA_UNKNOWN; } -bool minmea_parse_gprmc(struct minmea_gprmc *frame, const char *sentence) +bool minmea_parse_rmc(struct minmea_sentence_rmc *frame, const char *sentence) { // $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62 char type[6]; @@ -297,7 +297,7 @@ bool minmea_parse_gprmc(struct minmea_gprmc *frame, const char *sentence) &frame->date, &frame->variation, &frame->variation_scale, &variation_direction)) return false; - if (strcmp(type, "GPRMC")) + if (strcmp(type+2, "RMC")) return false; frame->valid = (validity == 'A'); @@ -308,7 +308,7 @@ bool minmea_parse_gprmc(struct minmea_gprmc *frame, const char *sentence) return true; } -bool minmea_parse_gpgga(struct minmea_gpgga *frame, const char *sentence) +bool minmea_parse_gga(struct minmea_sentence_gga *frame, const char *sentence) { // $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47 char type[6]; @@ -327,7 +327,7 @@ bool minmea_parse_gpgga(struct minmea_gpgga *frame, const char *sentence) &frame->height, &frame->height_scale, &frame->height_units, &frame->dgps_age)) return false; - if (strcmp(type, "GPGGA")) + if (strcmp(type+2, "GGA")) return false; frame->latitude *= latitude_direction; @@ -336,7 +336,7 @@ bool minmea_parse_gpgga(struct minmea_gpgga *frame, const char *sentence) return true; } -bool minmea_parse_gpgsa(struct minmea_gpgsa *frame, const char *sentence) +bool minmea_parse_gsa(struct minmea_sentence_gsa *frame, const char *sentence) { // $GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39 char type[6]; @@ -366,7 +366,7 @@ bool minmea_parse_gpgsa(struct minmea_gpgsa *frame, const char *sentence) )){ return false; } - if (strcmp(type, "GPGSA")) + if (strcmp(type+2, "GSA")) return false; return true; diff --git a/minmea.h b/minmea.h index 72b4a7a..df3edf0 100644 --- a/minmea.h +++ b/minmea.h @@ -23,12 +23,12 @@ extern "C" { #define MINMEA_MAX_LENGTH 80 -enum minmea_type { +enum minmea_sentence_id { MINMEA_INVALID = -1, MINMEA_UNKNOWN = 0, - MINMEA_GPRMC, - MINMEA_GPGGA, - MINMEA_GPGSA, + MINMEA_SENTENCE_RMC, + MINMEA_SENTENCE_GGA, + MINMEA_SENTENCE_GSA, }; struct minmea_date { @@ -44,7 +44,7 @@ struct minmea_time { int microseconds; }; -struct minmea_gprmc { +struct minmea_sentence_rmc { struct minmea_time time; bool valid; int latitude, latitude_scale; @@ -55,7 +55,7 @@ struct minmea_gprmc { int variation, variation_scale; }; -struct minmea_gpgga { +struct minmea_sentence_gga { struct minmea_time time; int latitude, latitude_scale; int longitude, longitude_scale; @@ -67,18 +67,18 @@ struct minmea_gpgga { int dgps_age; }; -enum minmea_gpgsa_mode { +enum minmea_gsa_mode { MINMEA_GPGSA_MODE_AUTO = 'A', MINMEA_GPGSA_MODE_FORCED = 'M', }; -enum minmea_gpgsa_fix_type { +enum minmea_gsa_fix_type { MINMEA_GPGSA_FIX_NONE = 1, MINMEA_GPGSA_FIX_2D = 2, MINMEA_GPGSA_FIX_3D = 3, }; -struct minmea_gpgsa { +struct minmea_sentence_gsa { char mode; int fix_type; int sats[12]; @@ -88,14 +88,14 @@ struct minmea_gpgsa { }; /** - * Check sequence validity and checksum. Returns true for valid sequences. + * Check sentence validity and checksum. Returns true for valid sentences. */ bool minmea_check(const char *sentence); /** - * Determine sequence type. + * Determine sentence identifier. */ -enum minmea_type minmea_type(const char *sequence); +enum minmea_sentence_id minmea_sentence_id(const char *sentence); /** * Scanf-like processor for NMEA sentences. Supports the following formats: @@ -111,11 +111,11 @@ enum minmea_type minmea_type(const char *sequence); bool minmea_scan(const char *sentence, const char *format, ...); /* - * Parse a specific type of frame. Return true on success. + * Parse a specific type of sentence. Return true on success. */ -bool minmea_parse_gprmc(struct minmea_gprmc *frame, const char *sentence); -bool minmea_parse_gpgga(struct minmea_gpgga *frame, const char *sentence); -bool minmea_parse_gpgsa(struct minmea_gpgsa *frame, const char *sentence); +bool minmea_parse_rmc(struct minmea_sentence_rmc *frame, const char *sentence); +bool minmea_parse_gga(struct minmea_sentence_gga *frame, const char *sentence); +bool minmea_parse_gsa(struct minmea_sentence_gsa *frame, const char *sentence); /** * Convert GPS UTC date/time representation to a UNIX timestamp. diff --git a/tests.c b/tests.c index 4fdd324..4d52ed4 100644 --- a/tests.c +++ b/tests.c @@ -284,11 +284,11 @@ START_TEST(test_minmea_scan_complex2) } END_TEST -START_TEST(test_minmea_parse_gprmc1) +START_TEST(test_minmea_parse_rmc1) { const char *sentence = "$GPRMC,081836.75,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E"; - struct minmea_gprmc frame = {}; - struct minmea_gprmc expected = { + struct minmea_sentence_rmc frame = {}; + struct minmea_sentence_rmc expected = { .time = { 8, 18, 36, 750000 }, .valid = true, .latitude = -375165, @@ -304,16 +304,16 @@ START_TEST(test_minmea_parse_gprmc1) .variation_scale = 10, }; ck_assert(minmea_check(sentence) == true); - ck_assert(minmea_parse_gprmc(&frame, sentence) == true); + ck_assert(minmea_parse_rmc(&frame, sentence) == true); ck_assert(!memcmp(&frame, &expected, sizeof(frame))); } END_TEST -START_TEST(test_minmea_parse_gprmc2) +START_TEST(test_minmea_parse_rmc2) { const char *sentence = "$GPRMC,,A,3751.65,N,14507.36,W,,,,,"; - struct minmea_gprmc frame = {}; - struct minmea_gprmc expected = { + struct minmea_sentence_rmc frame = {}; + struct minmea_sentence_rmc expected = { .time = { -1, -1, -1, -1 }, .valid = true, .latitude = 375165, @@ -323,16 +323,16 @@ START_TEST(test_minmea_parse_gprmc2) .date = { -1, -1, -1 }, }; ck_assert(minmea_check(sentence) == true); - ck_assert(minmea_parse_gprmc(&frame, sentence) == true); + ck_assert(minmea_parse_rmc(&frame, sentence) == true); ck_assert(!memcmp(&frame, &expected, sizeof(frame))); } END_TEST -START_TEST(test_minmea_parse_gpgga1) +START_TEST(test_minmea_parse_gga1) { const char *sentence = "$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47"; - struct minmea_gpgga frame = {}; - struct minmea_gpgga expected = { + struct minmea_sentence_gga frame = {}; + struct minmea_sentence_gga expected = { .time = { 12, 35, 19, 0 }, .latitude = 4807038, .latitude_scale = 1000, @@ -351,16 +351,16 @@ START_TEST(test_minmea_parse_gpgga1) .dgps_age = 0, }; ck_assert(minmea_check(sentence) == true); - ck_assert(minmea_parse_gpgga(&frame, sentence) == true); + ck_assert(minmea_parse_gga(&frame, sentence) == true); ck_assert(!memcmp(&frame, &expected, sizeof(frame))); } END_TEST -START_TEST(test_minmea_parse_gpgsa1) +START_TEST(test_minmea_parse_gsa1) { const char *sentence = "$GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39"; - struct minmea_gpgsa frame = {}; - struct minmea_gpgsa expected = { + struct minmea_sentence_gsa frame = {}; + struct minmea_sentence_gsa expected = { .mode = MINMEA_GPGSA_MODE_AUTO, .fix_type = MINMEA_GPGSA_FIX_3D, .sats = { 4, 5, 0, 9, 12, 0, 0, 24, 0, 0, 0, 0 }, @@ -372,7 +372,7 @@ START_TEST(test_minmea_parse_gpgsa1) .vdop_scale = 10 }; ck_assert(minmea_check(sentence) == true); - ck_assert(minmea_parse_gpgsa(&frame, sentence) == true); + ck_assert(minmea_parse_gsa(&frame, sentence) == true); ck_assert(!memcmp(&frame, &expected, sizeof(frame))); } END_TEST @@ -387,20 +387,20 @@ START_TEST(test_minmea_usage1) }; for (const char **sentence=sentences; *sentence; sentence++) { - switch (minmea_type(*sentence)) { - case MINMEA_GPRMC: { - struct minmea_gprmc frame; - ck_assert(minmea_parse_gprmc(&frame, *sentence) == true); + switch (minmea_sentence_id(*sentence)) { + case MINMEA_SENTENCE_RMC: { + struct minmea_sentence_rmc frame; + ck_assert(minmea_parse_rmc(&frame, *sentence) == true); } break; - case MINMEA_GPGGA: { - struct minmea_gpgga frame; - ck_assert(minmea_parse_gpgga(&frame, *sentence) == true); + case MINMEA_SENTENCE_GGA: { + struct minmea_sentence_gga frame; + ck_assert(minmea_parse_gga(&frame, *sentence) == true); } break; - case MINMEA_GPGSA: { - struct minmea_gpgsa frame; - ck_assert(minmea_parse_gpgsa(&frame, *sentence) == true); + case MINMEA_SENTENCE_GSA: { + struct minmea_sentence_gsa frame; + ck_assert(minmea_parse_gsa(&frame, *sentence) == true); } break; @@ -486,10 +486,10 @@ Suite *minmea_suite(void) suite_add_tcase(s, tc_scan); TCase *tc_parse = tcase_create("minmea_parse"); - tcase_add_test(tc_parse, test_minmea_parse_gprmc1); - tcase_add_test(tc_parse, test_minmea_parse_gprmc2); - tcase_add_test(tc_parse, test_minmea_parse_gpgga1); - tcase_add_test(tc_parse, test_minmea_parse_gpgsa1); + tcase_add_test(tc_parse, test_minmea_parse_rmc1); + tcase_add_test(tc_parse, test_minmea_parse_rmc2); + tcase_add_test(tc_parse, test_minmea_parse_gga1); + tcase_add_test(tc_parse, test_minmea_parse_gsa1); suite_add_tcase(s, tc_parse); TCase *tc_usage = tcase_create("minmea_usage");