Переглянути джерело

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.
lvitya 9 роки тому
батько
коміт
95f6beec4f
5 змінених файлів з 139 додано та 13 видалено
  1. 2 1
      README.md
  2. 17 0
      example.c
  3. 36 0
      minmea.c
  4. 19 4
      minmea.h
  5. 65 8
      tests.c

+ 2 - 1
README.md

@@ -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 - 0
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 - 0
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)

+ 19 - 4
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.

+ 65 - 8
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");