Add $--VTG sentences.
* Fix padding problem in test_minmea_parse_gll1 * Add support for $--VTG sentences. * Add tests for $--VTG sentences. * Fix padding problem in test_minmea_parse_gll1. 2nd attempt.
This commit is contained in:
parent
ade6621a59
commit
95f6beec4f
@ -24,8 +24,9 @@ systems.
|
||||
* ``GLL`` (Geographic Position: Latitude/Longitude)
|
||||
* ``GST`` (Pseudorange Noise Statistics)
|
||||
* ``GSV`` (Satellites in view)
|
||||
* ``VTG`` (Track made good and Ground speed)
|
||||
|
||||
Adding support for more sentences is trivial; see ``minmea.c`` source.
|
||||
Adding support for more sentences is trivial; see ``minmea.c`` source. Good documentation on NMEA is at http://www.catb.org/gpsd/NMEA.html
|
||||
|
||||
## Fractional number format
|
||||
|
||||
|
17
example.c
17
example.c
@ -90,6 +90,23 @@ int main(void)
|
||||
}
|
||||
} break;
|
||||
|
||||
case MINMEA_SENTENCE_VTG: {
|
||||
struct minmea_sentence_vtg frame;
|
||||
if (minmea_parse_vtg(&frame, line)) {
|
||||
printf(INDENT_SPACES "$xxVTG: true track degrees = %f\n",
|
||||
minmea_tofloat(&frame.true_track_degrees));
|
||||
printf(INDENT_SPACES " magnetic track degrees = %f\n",
|
||||
minmea_tofloat(&frame.magnetic_track_degrees));
|
||||
printf(INDENT_SPACES " speed knots = %f\n",
|
||||
minmea_tofloat(&frame.speed_knots));
|
||||
printf(INDENT_SPACES " speed kph = %f\n",
|
||||
minmea_tofloat(&frame.speed_kph));
|
||||
}
|
||||
else {
|
||||
printf(INDENT_SPACES "$xxVTG sentence is not parsed\n");
|
||||
}
|
||||
} break;
|
||||
|
||||
case MINMEA_INVALID: {
|
||||
printf(INDENT_SPACES "$xxxxx sentence is not valid\n");
|
||||
} break;
|
||||
|
36
minmea.c
36
minmea.c
@ -369,6 +369,8 @@ enum minmea_sentence_id minmea_sentence_id(const char *sentence, bool strict)
|
||||
return MINMEA_SENTENCE_GST;
|
||||
if (!strcmp(type+2, "GSV"))
|
||||
return MINMEA_SENTENCE_GSV;
|
||||
if (!strcmp(type+2, "VTG"))
|
||||
return MINMEA_SENTENCE_VTG;
|
||||
|
||||
return MINMEA_UNKNOWN;
|
||||
}
|
||||
@ -547,6 +549,40 @@ bool minmea_parse_gsv(struct minmea_sentence_gsv *frame, const char *sentence)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool minmea_parse_vtg(struct minmea_sentence_vtg *frame, const char *sentence)
|
||||
{
|
||||
// $GPVTG,054.7,T,034.4,M,005.5,N,010.2,K*48
|
||||
// $GPVTG,156.1,T,140.9,M,0.0,N,0.0,K*41
|
||||
// $GPVTG,096.5,T,083.5,M,0.0,N,0.0,K,D*22
|
||||
// $GPVTG,188.36,T,,M,0.820,N,1.519,K,A*3F
|
||||
char type[6];
|
||||
char c_true, c_magnetic, c_knots, c_kph, c_faa_mode;
|
||||
|
||||
if (!minmea_scan(sentence, "tfcfcfcfc;c",
|
||||
type,
|
||||
&frame->true_track_degrees,
|
||||
&c_true,
|
||||
&frame->magnetic_track_degrees,
|
||||
&c_magnetic,
|
||||
&frame->speed_knots,
|
||||
&c_knots,
|
||||
&frame->speed_kph,
|
||||
&c_kph,
|
||||
&c_faa_mode))
|
||||
return false;
|
||||
if (strcmp(type+2, "VTG"))
|
||||
return false;
|
||||
// check chars
|
||||
if (c_true != 'T' ||
|
||||
c_magnetic != 'M' ||
|
||||
c_knots != 'N' ||
|
||||
c_kph != 'K')
|
||||
return false;
|
||||
frame->faa_mode = c_faa_mode;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int minmea_gettime(struct timespec *ts, const struct minmea_date *date, const struct minmea_time *time_)
|
||||
{
|
||||
if (date->year == -1 || time_->hours == -1)
|
||||
|
23
minmea.h
23
minmea.h
@ -31,6 +31,7 @@ enum minmea_sentence_id {
|
||||
MINMEA_SENTENCE_GLL,
|
||||
MINMEA_SENTENCE_GST,
|
||||
MINMEA_SENTENCE_GSV,
|
||||
MINMEA_SENTENCE_VTG,
|
||||
};
|
||||
|
||||
struct minmea_float {
|
||||
@ -79,10 +80,15 @@ enum minmea_gll_status {
|
||||
MINMEA_GLL_STATUS_DATA_NOT_VALID = 'V',
|
||||
};
|
||||
|
||||
enum minmea_gll_mode {
|
||||
MINMEA_GLL_MODE_AUTONOMOUS = 'A',
|
||||
MINMEA_GLL_MODE_DPGS = 'D',
|
||||
MINMEA_GLL_MODE_DR = 'E',
|
||||
// FAA mode added to some fields in NMEA 2.3.
|
||||
enum minmea_faa_mode {
|
||||
MINMEA_FAA_MODE_AUTONOMOUS = 'A',
|
||||
MINMEA_FAA_MODE_DIFFERENTIAL = 'D',
|
||||
MINMEA_FAA_MODE_ESTIMATED = 'E',
|
||||
MINMEA_FAA_MODE_MANUAL = 'M',
|
||||
MINMEA_FAA_MODE_SIMULATED = 'S',
|
||||
MINMEA_FAA_MODE_NOT_VALID = 'N',
|
||||
MINMEA_FAA_MODE_PRECISE = 'P',
|
||||
};
|
||||
|
||||
struct minmea_sentence_gll {
|
||||
@ -138,6 +144,14 @@ struct minmea_sentence_gsv {
|
||||
struct minmea_sat_info sats[4];
|
||||
};
|
||||
|
||||
struct minmea_sentence_vtg {
|
||||
struct minmea_float true_track_degrees;
|
||||
struct minmea_float magnetic_track_degrees;
|
||||
struct minmea_float speed_knots;
|
||||
struct minmea_float speed_kph;
|
||||
enum minmea_faa_mode faa_mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate raw sentence checksum. Does not check sentence integrity.
|
||||
*/
|
||||
@ -180,6 +194,7 @@ bool minmea_parse_gsa(struct minmea_sentence_gsa *frame, const char *sentence);
|
||||
bool minmea_parse_gll(struct minmea_sentence_gll *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);
|
||||
bool minmea_parse_vtg(struct minmea_sentence_vtg *frame, const char *sentence);
|
||||
|
||||
/**
|
||||
* Convert GPS UTC date/time representation to a UNIX timestamp.
|
||||
|
73
tests.c
73
tests.c
@ -569,14 +569,19 @@ END_TEST
|
||||
START_TEST(test_minmea_parse_gll1)
|
||||
{
|
||||
const char *sentence = "$GPGLL,3723.2475,N,12158.3416,W,161229.487,A,A*41";
|
||||
struct minmea_sentence_gll frame = {};
|
||||
struct minmea_sentence_gll expected = {
|
||||
.latitude = { 37232475, 10000 },
|
||||
.longitude = { -121583416, 10000 },
|
||||
.time = { 16, 12, 29, 487000 },
|
||||
.status = MINMEA_GLL_STATUS_DATA_VALID,
|
||||
.mode = MINMEA_GLL_MODE_AUTONOMOUS,
|
||||
};
|
||||
struct minmea_sentence_gll frame;
|
||||
struct minmea_sentence_gll expected;
|
||||
|
||||
// clear structs before initialization to enable use of memcmp()
|
||||
// todo: add for other structs
|
||||
memset(&frame, 0, sizeof(frame));
|
||||
memset(&expected, 0, sizeof(expected));
|
||||
|
||||
expected.latitude = (struct minmea_float){ 37232475, 10000 };
|
||||
expected.longitude = (struct minmea_float){ -121583416, 10000 };
|
||||
expected.time = (struct minmea_time){ 16, 12, 29, 487000 };
|
||||
expected.status = MINMEA_GLL_STATUS_DATA_VALID;
|
||||
expected.mode = MINMEA_FAA_MODE_AUTONOMOUS;
|
||||
|
||||
ck_assert(minmea_check(sentence, false) == true);
|
||||
ck_assert(minmea_check(sentence, true) == true);
|
||||
@ -815,6 +820,50 @@ START_TEST(test_minmea_parse_gsv5)
|
||||
END_TEST
|
||||
|
||||
|
||||
START_TEST(test_minmea_parse_vtg1)
|
||||
{
|
||||
const char *sentence = "$GPVTG,054.7,T,034.4,M,005.5,N,010.2,K*48";
|
||||
// clear structs before initialization to enable use of memcmp()
|
||||
struct minmea_sentence_vtg frame = {};
|
||||
struct minmea_sentence_vtg expected = {};
|
||||
|
||||
expected = (struct minmea_sentence_vtg){
|
||||
.true_track_degrees = { 547, 10 },
|
||||
.magnetic_track_degrees = { 344, 10 },
|
||||
.speed_knots = { 55, 10 },
|
||||
.speed_kph = { 102, 10 },
|
||||
.faa_mode = 0,
|
||||
};
|
||||
|
||||
ck_assert(minmea_check(sentence, false) == true);
|
||||
ck_assert(minmea_check(sentence, true) == true);
|
||||
ck_assert(minmea_parse_vtg(&frame, sentence) == true);
|
||||
ck_assert(!memcmp(&frame, &expected, sizeof(frame)));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_minmea_parse_vtg2)
|
||||
{
|
||||
const char *sentence = "$GPVTG,188.36,T,,M,0.820,N,1.519,K,A*3F";
|
||||
// clear structs before initialization to enable use of memcmp()
|
||||
struct minmea_sentence_vtg frame = {};
|
||||
struct minmea_sentence_vtg expected = {};
|
||||
|
||||
expected = (struct minmea_sentence_vtg){
|
||||
.true_track_degrees = { 18836, 100 },
|
||||
.magnetic_track_degrees = { 0, 0 },
|
||||
.speed_knots = { 820, 1000 },
|
||||
.speed_kph = { 1519, 1000 },
|
||||
.faa_mode = MINMEA_FAA_MODE_AUTONOMOUS,
|
||||
};
|
||||
|
||||
ck_assert(minmea_check(sentence, false) == true);
|
||||
ck_assert(minmea_check(sentence, true) == true);
|
||||
ck_assert(minmea_parse_vtg(&frame, sentence) == true);
|
||||
ck_assert(!memcmp(&frame, &expected, sizeof(frame)));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_minmea_usage1)
|
||||
{
|
||||
const char *sentences[] = {
|
||||
@ -823,6 +872,7 @@ START_TEST(test_minmea_usage1)
|
||||
"$GNGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1",
|
||||
"$GPGLL,3723.2475,N,12158.3416,W,161229.487,A,A*41",
|
||||
"$GPGST,024603.00,3.2,6.6,4.7,47.3,5.8,5.6,22.0*58",
|
||||
"$GPVTG,096.5,T,083.5,M,0.0,N,0.0,K,D*22",
|
||||
NULL,
|
||||
};
|
||||
|
||||
@ -853,6 +903,11 @@ START_TEST(test_minmea_usage1)
|
||||
ck_assert(minmea_parse_gst(&frame, *sentence) == true);
|
||||
} break;
|
||||
|
||||
case MINMEA_SENTENCE_VTG: {
|
||||
struct minmea_sentence_vtg frame;
|
||||
ck_assert(minmea_parse_vtg(&frame, *sentence) == true);
|
||||
} break;
|
||||
|
||||
default: {
|
||||
} break;
|
||||
}
|
||||
@ -963,6 +1018,8 @@ static Suite *minmea_suite(void)
|
||||
tcase_add_test(tc_parse, test_minmea_parse_gsv3);
|
||||
tcase_add_test(tc_parse, test_minmea_parse_gsv4);
|
||||
tcase_add_test(tc_parse, test_minmea_parse_gsv5);
|
||||
tcase_add_test(tc_parse, test_minmea_parse_vtg1);
|
||||
tcase_add_test(tc_parse, test_minmea_parse_vtg2);
|
||||
suite_add_tcase(s, tc_parse);
|
||||
|
||||
TCase *tc_usage = tcase_create("minmea_usage");
|
||||
|
Loading…
Reference in New Issue
Block a user