diff --git a/README.md b/README.md index 2178428..90aee1f 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ systems. * ``GGA`` (Fix Data) * ``GSA`` (DOP and active satellites) * ``GST`` (Pseudorange Noise Statistics) +* ``GSV`` (Satellites in view) Adding support for more sentences is trivial; see ``minmea.c`` source. @@ -79,6 +80,20 @@ The library doesn't perform this conversion automatically for the following reas printf("$GPGGA: fix quality: %d\n", frame.fix_quality); } } break; + + case MINMEA_SENTENCE_GSV: { + struct minmea_sentence_gsv frame; + if (minmea_parse_gsv(&frame, line)) { + printf("$GPGSV: message %d of %d\n", frame.msg_nr, frame.total_msgs); + printf("$GPGSV: sattelites in view: %d\n", frame.total_sats); + for (int i = 0; i < 4; i++) + printf("$GPGSV: sat nr %d, elevation: %d, azimuth: %d, snr: %d dbm\n", + frame.sats[i].nr, + frame.sats[i].elevation, + frame.sats[i].azimuth, + frame.sats[i].snr); + } + } break; } } ``` diff --git a/example.c b/example.c index 01152b0..abc4371 100644 --- a/example.c +++ b/example.c @@ -62,6 +62,20 @@ int main() } } break; + case MINMEA_SENTENCE_GSV: { + struct minmea_sentence_gsv frame; + if (minmea_parse_gsv(&frame, line)) { + printf("$GPGSV: message %d of %d\n", frame.msg_nr, frame.total_msgs); + printf("$GPGSV: sattelites in view: %d\n", frame.total_sats); + for (int i = 0; i < 4; i++) + printf("$GPGSV: sat nr %d, elevation: %d, azimuth: %d, snr: %d dbm\n", + frame.sats[i].nr, + frame.sats[i].elevation, + frame.sats[i].azimuth, + frame.sats[i].snr); + } + } break; + default: { } break; } diff --git a/minmea.c b/minmea.c index cdacf40..6cf4457 100644 --- a/minmea.c +++ b/minmea.c @@ -321,6 +321,8 @@ enum minmea_sentence_id minmea_sentence_id(const char *sentence) return MINMEA_SENTENCE_GSA; if (!strcmp(type+2, "GST")) return MINMEA_SENTENCE_GST; + if (!strcmp(type+2, "GSV")) + return MINMEA_SENTENCE_GSV; return MINMEA_UNKNOWN; } @@ -441,6 +443,40 @@ bool minmea_parse_gst(struct minmea_sentence_gst *frame, const char *sentence) return true; } +bool minmea_parse_gsv(struct minmea_sentence_gsv *frame, const char *sentence) +{ + // $GPGSV,3,1,11,03,03,111,00,04,15,270,00,06,01,010,00,13,06,292,00*74 + char type[6]; + + if (!minmea_scan(sentence, "tiiiiiiiiiiiiiiiiiii", + type, + &frame->total_msgs, + &frame->msg_nr, + &frame->total_sats, + &frame->sats[0].nr, + &frame->sats[0].elevation, + &frame->sats[0].azimuth, + &frame->sats[0].snr, + &frame->sats[1].nr, + &frame->sats[1].elevation, + &frame->sats[1].azimuth, + &frame->sats[1].snr, + &frame->sats[2].nr, + &frame->sats[2].elevation, + &frame->sats[2].azimuth, + &frame->sats[2].snr, + &frame->sats[3].nr, + &frame->sats[3].elevation, + &frame->sats[3].azimuth, + &frame->sats[3].snr + )) { + return false; + } + if (strcmp(type+2, "GSV")) + return false; + + return true; +} int minmea_gettimeofday(struct timeval *tv, const struct minmea_date *date, const struct minmea_time *time) { diff --git a/minmea.h b/minmea.h index 9752233..ddb417b 100644 --- a/minmea.h +++ b/minmea.h @@ -32,6 +32,7 @@ enum minmea_sentence_id { MINMEA_SENTENCE_GGA, MINMEA_SENTENCE_GSA, MINMEA_SENTENCE_GST, + MINMEA_SENTENCE_GSV, }; struct minmea_date { @@ -101,6 +102,20 @@ struct minmea_sentence_gsa { int vdop, vdop_scale; }; +struct minmea_sat_info { + int nr; + int elevation; + int azimuth; + int snr; +}; + +struct minmea_sentence_gsv { + int total_msgs; + int msg_nr; + int total_sats; + struct minmea_sat_info sats[4]; +}; + /** * Check sentence validity and checksum. Returns true for valid sentences. */ @@ -136,6 +151,7 @@ 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); bool minmea_parse_gst(struct minmea_sentence_gst *frame, const char *sentence); +bool minmea_parse_gsv(struct minmea_sentence_gsv *frame, const char *sentence); /** * Convert GPS UTC date/time representation to a UNIX timestamp. diff --git a/tests.c b/tests.c index 6a148a1..6e07252 100644 --- a/tests.c +++ b/tests.c @@ -516,6 +516,47 @@ START_TEST(test_minmea_parse_gsa1) } END_TEST +START_TEST(test_minmea_parse_gsv1) +{ + const char *sentence = "$GPGSV,3,3,11,22,42,067,42,24,14,311,43,27,05,244,00,,,,*4D"; + struct minmea_sentence_gsv frame = {}; + static const struct minmea_sentence_gsv expected = { + .total_msgs = 3, + .msg_nr = 3, + .total_sats = 11, + .sats = { + { + .nr = 22, + .elevation = 42, + .azimuth = 67, + .snr = 42 + }, + { + .nr = 24, + .elevation = 14, + .azimuth = 311, + .snr = 43 + }, + { + .nr = 27, + .elevation = 5, + .azimuth = 244, + .snr = 0 + }, + { + .nr = 0, + .elevation = 0, + .azimuth = 0, + .snr = 0 + } + } + }; + ck_assert(minmea_check(sentence) == true); + ck_assert(minmea_parse_gsv(&frame, sentence) == true); + ck_assert(!memcmp(&frame, &expected, sizeof(frame))); +} +END_TEST + START_TEST(test_minmea_usage1) { const char *sentences[] = { @@ -642,6 +683,7 @@ Suite *minmea_suite(void) tcase_add_test(tc_parse, test_minmea_parse_gga1); tcase_add_test(tc_parse, test_minmea_parse_gsa1); tcase_add_test(tc_parse, test_minmea_parse_gst1); + tcase_add_test(tc_parse, test_minmea_parse_gsv1); suite_add_tcase(s, tc_parse); TCase *tc_usage = tcase_create("minmea_usage");