diff --git a/example.c b/example.c index e973814..01152b0 100644 --- a/example.c +++ b/example.c @@ -43,6 +43,25 @@ int main() } } break; + case MINMEA_SENTENCE_GST: { + struct minmea_sentence_gst frame; + if (minmea_parse_gst(&frame, line)) { + printf("+++ raw latitude,longitude and altitude error deviation: (%d/%d,%d/%d,%d/d)\n", + frame.latitude_error_deviation, frame.latitude_error_deviation_scale, + frame.longitude_error_deviation, frame.longitude_error_deviation_scale, + frame.altitude_error_deviation, frame.altitude_error_deviation_scale); + printf("+++ fixed point latitude,longitude and altitude error deviation \ + scaled to one decimal place: (%d,%d,%d)\n", + minmea_rescale(frame.latitude_error_deviation, frame.latitude_error_deviation_scale,10), + minmea_rescale(frame.longitude_error_deviation, frame.longitude_error_deviation_scale,10), + minmea_rescale(frame.altitude_error_deviation, frame.altitude_error_deviation_scale,10)); + printf("+++ floating point degree latitude,longitude and altitude error deviation: (%f,%f,%f)", + minmea_coord(frame.latitude_error_deviation, frame.latitude_error_deviation_scale), + minmea_coord(frame.longitude_error_deviation, frame.longitude_error_deviation_scale), + minmea_coord(frame.altitude_error_deviation, frame.altitude_error_deviation_scale)); + } + } break; + default: { } break; } diff --git a/minmea.c b/minmea.c index 72f1049..cdacf40 100644 --- a/minmea.c +++ b/minmea.c @@ -319,6 +319,8 @@ enum minmea_sentence_id minmea_sentence_id(const char *sentence) return MINMEA_SENTENCE_GGA; if (!strcmp(type+2, "GSA")) return MINMEA_SENTENCE_GSA; + if (!strcmp(type+2, "GST")) + return MINMEA_SENTENCE_GST; return MINMEA_UNKNOWN; } @@ -417,6 +419,29 @@ bool minmea_parse_gsa(struct minmea_sentence_gsa *frame, const char *sentence) return true; } +bool minmea_parse_gst(struct minmea_sentence_gst *frame, const char *sentence) +{ + // $GPGST,024603.00,3.2,6.6,4.7,47.3,5.8,5.6,22.0*58 + char type[6]; + + if (!minmea_scan(sentence, "tTfffffff", + type, + &frame->time, + &frame->rms_deviation, &frame->rms_deviation_scale, + &frame->semi_major_deviation, &frame->semi_major_deviation_scale, + &frame->semi_minor_deviation, &frame->semi_minor_deviation_scale, + &frame->semi_major_orientation, &frame->semi_major_orientation_scale, + &frame->latitude_error_deviation, &frame->latitude_error_deviation_scale, + &frame->longitude_error_deviation, &frame->longitude_error_deviation_scale, + &frame->altitude_error_deviation, &frame->altitude_error_deviation_scale)) + return false; + if (strcmp(type+2, "GST")) + return false; + + return true; +} + + int minmea_gettimeofday(struct timeval *tv, const struct minmea_date *date, const struct minmea_time *time) { if (date->year == -1 || time->hours == -1) diff --git a/minmea.h b/minmea.h index 8fab9c0..9752233 100644 --- a/minmea.h +++ b/minmea.h @@ -31,6 +31,7 @@ enum minmea_sentence_id { MINMEA_SENTENCE_RMC, MINMEA_SENTENCE_GGA, MINMEA_SENTENCE_GSA, + MINMEA_SENTENCE_GST, }; struct minmea_date { @@ -69,6 +70,17 @@ struct minmea_sentence_gga { int dgps_age; }; +struct minmea_sentence_gst { + struct minmea_time time; + int rms_deviation, rms_deviation_scale; + int semi_major_deviation, semi_major_deviation_scale; + int semi_minor_deviation, semi_minor_deviation_scale; + int semi_major_orientation, semi_major_orientation_scale; + int latitude_error_deviation, latitude_error_deviation_scale; + int longitude_error_deviation, longitude_error_deviation_scale; + int altitude_error_deviation, altitude_error_deviation_scale; +}; + enum minmea_gsa_mode { MINMEA_GPGSA_MODE_AUTO = 'A', MINMEA_GPGSA_MODE_FORCED = 'M', @@ -123,6 +135,7 @@ bool minmea_scan(const char *sentence, const char *format, ...); 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); /** * Convert GPS UTC date/time representation to a UNIX timestamp. diff --git a/tests.c b/tests.c index cee01b1..970c782 100644 --- a/tests.c +++ b/tests.c @@ -34,6 +34,7 @@ static const char *valid_sequences[] = { "$GPGLL,5106.94086,N,01701.51680,E,123204.00,A,A*63", "$GPRMC,123205.00,A,5106.94085,N,01701.51689,E,0.016,,280214,,,A*7B", "$GPVTG,,T,,M,0.016,N,0.030,K,A*27", + "$GPGST,024603.00,3.2,6.6,4.7,47.3,5.8,5.6,22.0*58". NULL, }; @@ -351,6 +352,50 @@ START_TEST(test_minmea_scan_complex2) } END_TEST +START_TEST(test_minmea_scan_complex3) +{ + const char *sentence = "$GPGST,024603.00,3.2,6.6,4.7,47.3,5.8,5.6,22.0*58"; + char type[6]; + struct minmea_time time; + int rms_deviation, rms_deviation_scale; + int semi_major_deviation, semi_major_deviation_scale; + int semi_minor_deviation, semi_minor_deviation_scale; + int semi_major_orientation, semi_major_orientation_scale; + int latitude_error_deviation, latitude_error_deviation_scale; + int longitude_error_deviation, longitude_error_deviation_scale; + int altitude_error_deviation, altitude_error_deviation_scale; + ck_assert(minmea_scan(sentence, "tTfffffff", + type, + &time, + &rms_deviation, &rms_deviation_scale, + &semi_major_deviation, &semi_major_deviation_scale, + &semi_minor_deviation, &semi_minor_deviation_scale, + &semi_major_orientation, &semi_major_orientation_scale, + &latitude_error_deviation, &latitude_error_deviation_scale, + &longitude_error_deviation, &longitude_error_deviation_scale, + &altitude_error_deviation, &altitude_error_deviation_scale) == true); + ck_assert_str_eq(type, "GPGST"); + ck_assert_int_eq(time.hours, 2); + ck_assert_int_eq(time.minutes, 46); + ck_assert_int_eq(time.seconds, 3); + ck_assert_int_eq(time.microseconds, 0); + ck_assert_int_eq(rms_deviation, 32); + ck_assert_int_eq(rms_deviation_scale, 10); + ck_assert_int_eq(semi_major_deviation, 66); + ck_assert_int_eq(semi_major_deviation_scale, 10); + ck_assert_int_eq(semi_minor_deviation, 47); + ck_assert_int_eq(semi_minor_deviation_scale, 10); + ck_assert_int_eq(semi_major_orientation, 473); + ck_assert_int_eq(semi_major_orientation_scale, 10); + ck_assert_int_eq(latitude_error_deviation, 58); + ck_assert_int_eq(latitude_error_deviation, 10); + ck_assert_int_eq(longitude_error_deviation, 56); + ck_assert_int_eq(longitude_error_deviation, 10); + ck_assert_int_eq(altitude_error_deviation, 220); + ck_assert_int_eq(altitude_error_deviation_scale,10); +} +END_TEST + 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"; @@ -423,6 +468,33 @@ START_TEST(test_minmea_parse_gga1) } END_TEST +START_TEST(test_minmea_parse_gst1) +{ + const char *sentence = "$GPGST,024603.00,3.2,6.6,4.7,47.3,5.8,5.6,22.0*58"; + struct minmea_sentence_gst frame = {}; + struct minmea_sentence_gst expected = { + .time = { 2, 46, 3, 0 }, + .rms_deviation = 32, + .rms_deviation_scale = 10, + .semi_major_deviation = 66, + .semi_major_deviation_scale = 10, + .semi_minor_deviation = 47, + .semi_minor_deviation_scale = 10, + .semi_major_orientation = 473, + .semi_major_orientation_scale = 10, + .latitude_error_deviation = 58, + .latitude_error_deviation_scale = 10, + .longitude_error_deviation = 56, + .longitude_error_deviation_scale = 10, + .altitude_error_deviation = 220, + .altitude_error_deviation_scale = 10, + }; + ck_assert(minmea_check(sentence) == true); + ck_assert(minmea_parse_gst(&frame, sentence) == true); + ck_assert(!memcmp(&frame, &expected, sizeof(frame))); +} +END_TEST + START_TEST(test_minmea_parse_gsa1) { const char *sentence = "$GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39"; @@ -450,6 +522,7 @@ START_TEST(test_minmea_usage1) "$GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62", "$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47", "$GNGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1", + "$GPGST,024603.00,3.2,6.6,4.7,47.3,5.8,5.6,22.0*58", NULL, }; @@ -459,17 +532,21 @@ START_TEST(test_minmea_usage1) struct minmea_sentence_rmc frame; ck_assert(minmea_parse_rmc(&frame, *sentence) == true); } break; - + case MINMEA_SENTENCE_GGA: { struct minmea_sentence_gga frame; ck_assert(minmea_parse_gga(&frame, *sentence) == true); } break; - + case MINMEA_SENTENCE_GSA: { struct minmea_sentence_gsa frame; ck_assert(minmea_parse_gsa(&frame, *sentence) == true); } break; + case MINMEA_SENTENCE_GST: { + struct minmea_sentence_gst frame; + ck_assert(minmea_parse_gst(&frame, *sentence) == true); + } break; default: { } break; @@ -540,7 +617,7 @@ END_TEST Suite *minmea_suite(void) { Suite *s = suite_create ("minmea"); - + TCase *tc_check = tcase_create("minmea_check"); tcase_add_test(tc_check, test_minmea_check); suite_add_tcase(s, tc_check); @@ -557,7 +634,7 @@ Suite *minmea_suite(void) tcase_add_test(tc_scan, test_minmea_scan_complex1); tcase_add_test(tc_scan, test_minmea_scan_complex2); suite_add_tcase(s, tc_scan); - + TCase *tc_parse = tcase_create("minmea_parse"); tcase_add_test(tc_parse, test_minmea_parse_rmc1); tcase_add_test(tc_parse, test_minmea_parse_rmc2);