1
1
#include " gpgga.h"
2
2
3
- #include < iostream >
3
+ #include < cstring >
4
4
5
5
namespace globpos {
6
6
@@ -11,37 +11,29 @@ bool parseGPGGA(NmeaSentence* sentence, GlobPosDegMin& pos) {
11
11
int qualityVal = 0 ;
12
12
sscanf (quality.c_str (), " %d" , &qualityVal);
13
13
if (qualityVal < 1 ) {
14
- #ifdef GLOBPOS_PRINT_ERRORS
15
- fprintf (stdout, " Low signal quality: %d, skipping sentence\n " , qualityVal);
16
- #endif
17
14
return false ;
18
15
}
19
16
} else {
20
- #ifdef GLOBPOS_PRINT_ERRORS
21
- fprintf (stderr, " Unknown signal quality\n " );
22
- #endif
23
17
return false ;
24
18
}
25
19
26
20
// time
27
21
std::string time = sentence->safeGetData (0 );
28
22
if (!time .empty ()) {
29
- // TODO: parse timestamp
23
+ if (!parseTime (time .c_str (), pos.timestamp )) {
24
+ return false ;
25
+ }
30
26
} else {
31
- #ifdef GLOBPOS_PRINT_ERRORS
32
- fprintf (stderr, " Unknown time\n " );
33
- #endif
34
27
return false ;
35
28
}
36
29
37
30
// latitude
38
31
std::string latitude = sentence->safeGetData (1 );
39
32
if (!latitude.empty ()) {
40
- parseLatitude (latitude, pos.latitude );
33
+ if (!parseLatitude (latitude, pos.latitude )) {
34
+ return false ;
35
+ }
41
36
} else {
42
- #ifdef GLOBPOS_PRINT_ERRORS
43
- fprintf (stderr, " Unknown latitude\n " );
44
- #endif
45
37
return false ;
46
38
}
47
39
std::string latitudeDir = sentence->safeGetData (2 );
@@ -51,26 +43,19 @@ bool parseGPGGA(NmeaSentence* sentence, GlobPosDegMin& pos) {
51
43
else if (latitudeDir == " S" )
52
44
pos.latitude .direction = false ;
53
45
else {
54
- #ifdef GLOBPOS_PRINT_ERRORS
55
- fprintf (stderr, " Unknown latitude direction\n " );
56
- #endif
57
46
return false ;
58
47
}
59
48
} else {
60
- #ifdef GLOBPOS_PRINT_ERRORS
61
- fprintf (stderr, " Unknown latitude direction\n " );
62
- #endif
63
49
return false ;
64
50
}
65
51
66
52
// longitude
67
53
std::string longitude = sentence->safeGetData (3 );
68
54
if (!longitude.empty ()) {
69
- parseLongitude (longitude, pos.longitude );
55
+ if (!parseLongitude (longitude, pos.longitude )) {
56
+ return false ;
57
+ }
70
58
} else {
71
- #ifdef GLOBPOS_PRINT_ERRORS
72
- fprintf (stderr, " Unknown longitude\n " );
73
- #endif
74
59
return false ;
75
60
}
76
61
std::string longitudeDir = sentence->safeGetData (4 );
@@ -80,38 +65,105 @@ bool parseGPGGA(NmeaSentence* sentence, GlobPosDegMin& pos) {
80
65
else if (longitudeDir == " W" )
81
66
pos.longitude .direction = false ;
82
67
else {
83
- #ifdef GLOBPOS_PRINT_ERRORS
84
- fprintf (stderr, " Unknown longitude direction\n " );
85
- #endif
86
68
return false ;
87
69
}
88
70
} else {
89
- #ifdef GLOBPOS_PRINT_ERRORS
90
- fprintf (stderr, " Unknown longitude direction\n " );
91
- #endif
92
71
return false ;
93
72
}
94
73
95
74
return true ;
96
75
}
97
76
98
- bool parseCoordinate (const std::string& str, const char * format, GpsCoordDegMin& coord) {
99
- if (sscanf (str.c_str (), format, &coord.deg , &coord.minInt , &coord.minFract ) == 3 )
100
- return true ;
101
- else {
102
- #ifdef GLOBPOS_PRINT_ERRORS
103
- fprintf (stderr, " wrong coordinate string: %s\n " , str.c_str ());
104
- #endif
77
+ bool parseLatitude (const std::string& str, GpsCoordDegMin& coord) {
78
+ return sscanf (str.c_str (), " %02d%02d.%d" , &coord.deg , &coord.minInt , &coord.minFract ) == 3 ;
79
+ }
80
+
81
+ bool parseLongitude (const std::string& str, GpsCoordDegMin& coord) {
82
+ return sscanf (str.c_str (), " %03d%02d.%d" , &coord.deg , &coord.minInt , &coord.minFract ) == 3 ;
83
+ }
84
+
85
+ bool parseDateTime (const char * str, std::chrono::time_point<std::chrono::system_clock>& timestamp) {
86
+ std::tm tm ;
87
+ memset (&tm , 0 , sizeof (tm ));
88
+
89
+ long millis;
90
+ int filled = sscanf (str, " %04d%*c%02d%*c%02d%*c%02d%*c%02d%*c%02d%*c%06ld" ,
91
+ &tm .tm_year , &tm .tm_mon , &tm .tm_mday ,
92
+ &tm .tm_hour , &tm .tm_min , &tm .tm_sec ,
93
+ &millis);
94
+ if (filled < 6 ) {
105
95
return false ;
106
96
}
97
+
98
+ tm .tm_mon -= 1 ;
99
+ tm .tm_year -= 1900 ;
100
+ if (tm .tm_year < 70 ) {
101
+ tm .tm_year = 70 ;
102
+ }
103
+
104
+ time_t sec;
105
+ if (tm .tm_year == 70 && tm .tm_mon == 0 && tm .tm_mday == 1 ) {
106
+ sec = tm .tm_hour * 60 * 60 + tm .tm_min * 60 + tm .tm_sec ;
107
+ } else {
108
+ sec = timegm (&tm );
109
+ }
110
+
111
+ timestamp = std::chrono::system_clock::from_time_t (sec);
112
+
113
+ if (filled == 7 ) {
114
+ timestamp += std::chrono::milliseconds (millis);
115
+ }
116
+ return true ;
107
117
}
108
118
109
- bool parseLatitude (const std::string& str, GpsCoordDegMin& coord) {
110
- return parseCoordinate (str, " %02d%02d.%d" , coord);
119
+ // / Searches for decimal point and returns number of fractional digits.
120
+ int fractDigitsCnt (const std::string& numStr) {
121
+ size_t p = numStr.rfind (' .' );
122
+ if (p == std::string::npos) {
123
+ return 0 ;
124
+ }
125
+ return (int )(numStr.length () - p - 1 );
111
126
}
112
127
113
- bool parseLongitude (const std::string& str, GpsCoordDegMin& coord) {
114
- return parseCoordinate (str, " %03d%02d.%d" , coord);
128
+ // / Compile-time power computation.
129
+ template <int N, int P> struct Power
130
+ {
131
+ enum
132
+ {
133
+ val = N * Power<N, P - 1 >::val
134
+ };
135
+ };
136
+ template <int N> struct Power <N, 0 >
137
+ {
138
+ enum
139
+ {
140
+ val = 1
141
+ };
142
+ };
143
+
144
+ // / Run-time power of 10 computation.
145
+ long pow10 (int p) {
146
+ return (p == 0 ) ? 1 : 10 * pow10 (p - 1 );
147
+ }
148
+
149
+ bool parseTime (const char * str, std::chrono::time_point<std::chrono::system_clock>& timestamp) {
150
+ int hours, min, sec;
151
+ long millis;
152
+ int filled = sscanf (str, " %02d%02d%02d.%ld" , &hours, &min, &sec, &millis);
153
+ if (filled < 3 ) {
154
+ return false ;
155
+ }
156
+
157
+ timestamp += std::chrono::hours (hours);
158
+ timestamp += std::chrono::minutes (min);
159
+ timestamp += std::chrono::seconds (sec);
160
+
161
+ if (filled == 4 ) {
162
+ int fractDigits = fractDigitsCnt (str);
163
+ long order = Power<10 , 6 >::val / pow10 (fractDigits);
164
+ timestamp += std::chrono::milliseconds (millis * order);
165
+ }
166
+ return true ;
115
167
}
116
168
117
169
}
0 commit comments