14std::unique_ptr<GGA> GGA::create(std::unique_ptr<Message0183> baseMessage) {
15 std::string context =
"GGA::create";
16 if (baseMessage->getSentenceType() !=
"GGA") {
17 NMEALIB_RETURN_ERROR(NotGGAException(context,
"Expected sentence type 'GGA', got " + baseMessage->getSentenceType()));
21 std::string payload = baseMessage->getPayload();
22 std::istringstream ss(payload);
24 std::vector<std::string> fields;
26 while (std::getline(ss, token,
',')) {
27 fields.push_back(token);
31 if (!payload.empty() && payload.back() ==
',') {
36 if (!fields.empty()) {
37 fields.erase(fields.begin());
39 size_t messageSize = fields.size();
40 if (messageSize != 14 && messageSize != 12) {
41 NMEALIB_RETURN_ERROR(NotGGAException(context,
"Insufficient fields in GGA payload: expected 14 or 12, got " + std::to_string(fields.size()) +
". Payload: " + payload));
44 double timestamp = 0.0;
45 double latitude = 0.0;
46 double longitude = 0.0;
47 unsigned int gpsQuality = 0U;
48 unsigned int satellites = 0U;
50 double altitude = 0.0;
51 double geoidalSeparation = 0.0;
52 double dgpsAge = -1.0;
64 char latitudeDirection = fields[2].empty() ?
'\0' : fields[2][0];
65 char longitudeDirection = fields[4].empty() ?
'\0' : fields[4][0];
66 char altitudeUnits = fields[9].empty() ?
'\0' : fields[9][0];
67 char geoidalSeparationUnits = fields[11].empty() ?
'\0' : fields[11][0];
68 std::string dgpsReferenceStationId;
70 if (messageSize == 14) {
74 dgpsReferenceStationId = fields[13].empty() ?
"" : fields[13];
77 return std::unique_ptr<GGA>(
new GGA(std::move(*baseMessage),
89 geoidalSeparationUnits,
91 dgpsReferenceStationId));
94GGA::GGA(Message0183 baseMessage,
97 char latitudeDirection,
99 char longitudeDirection,
100 unsigned int gpsQuality,
101 unsigned int satellites,
105 double geoidalSeparation,
106 char geoidalSeparationUnits,
108 std::string dgpsReferenceStationId) noexcept
109 : Message0183(std::move(baseMessage)),
112 latitudeDirection_(latitudeDirection),
113 longitude_(longitude),
114 longitudeDirection_(longitudeDirection),
115 gpsQuality_(gpsQuality),
116 satellites_(satellites),
119 altitudeUnits_(altitudeUnits),
120 geoidalSeparation_(geoidalSeparation),
121 geoidalSeparationUnits_(geoidalSeparationUnits),
123 dgpsReferenceStationId_(std::move(dgpsReferenceStationId)) {}
125GGA::GGA(std::string talkerId,
128 char latitudeDirection,
130 char longitudeDirection,
131 unsigned int gpsQuality,
132 unsigned int satellites,
136 double geoidalSeparation,
137 char geoidalSeparationUnits,
139 std::string dgpsReferenceStationId)
152 geoidalSeparationUnits,
154 dgpsReferenceStationId))),
157 latitudeDirection_(latitudeDirection),
158 longitude_(longitude),
159 longitudeDirection_(longitudeDirection),
160 gpsQuality_(gpsQuality),
161 satellites_(satellites),
164 altitudeUnits_(altitudeUnits),
165 geoidalSeparation_(geoidalSeparation),
166 geoidalSeparationUnits_(geoidalSeparationUnits),
168 dgpsReferenceStationId_(std::move(dgpsReferenceStationId)) {}
171 return std::unique_ptr<GGA>(
new GGA(*
this));
175 std::ostringstream ss;
176 ss << this->toString(verbose);
177 std::ostringstream latStream;
178 latStream << std::setprecision(10) << latitude_;
179 const std::string latitudeStr = latStream.str();
181 std::ostringstream lonStream;
182 lonStream << std::setprecision(10) << longitude_;
183 const std::string longitudeStr = lonStream.str();
186 ss <<
"\tTimestamp: " << utcTime_ <<
"\n";
187 ss <<
"\tLatitude: " << latitudeStr <<
" " << latitudeDirection_ <<
"\n";
188 ss <<
"\tLongitude: " << longitudeStr <<
" " << longitudeDirection_ <<
"\n";
189 ss <<
"\tGPS Quality: " << gpsQuality_ <<
"\n";
190 ss <<
"\tSatellites: " << satellites_ <<
"\n";
191 ss <<
"\tHDOP: " << hdop_ <<
"\n";
192 ss <<
"\tAltitude: " << altitude_ <<
" " << altitudeUnits_ <<
"\n";
193 ss <<
"\tGeoidal Separation: " << geoidalSeparation_ <<
" " << geoidalSeparationUnits_ <<
"\n";
194 ss <<
"\tDGPS Age: " << dgpsAge_ <<
"\n";
195 ss <<
"\tDGPS Ref: " << dgpsReferenceStationId_;
198 ss <<
"Time=" << utcTime_
199 <<
", Lat=" << latitudeStr << latitudeDirection_
200 <<
", Lon=" << longitudeStr << longitudeDirection_
201 <<
", Qual=" << gpsQuality_
202 <<
", Sats=" << satellites_
203 <<
", HDOP=" << hdop_
204 <<
", Alt=" << altitude_ << altitudeUnits_
205 <<
", GeoSep=" << geoidalSeparation_ << geoidalSeparationUnits_
206 <<
", DGPSAge=" << dgpsAge_
207 <<
", DGPSRef=" << dgpsReferenceStationId_;
212std::string GGA::composeRaw(
const std::string& talkerId,
215 char latitudeDirection,
217 char longitudeDirection,
218 unsigned int gpsQuality,
219 unsigned int satellites,
223 double geoidalSeparation,
224 char geoidalSeparationUnits,
226 const std::string& dgpsReferenceStationId) {
227 std::ostringstream payloadStream;
228 payloadStream << talkerId <<
"GGA,";
229 payloadStream << std::fixed << std::setprecision(2) << std::setw(9) << std::setfill(
'0') << timestamp <<
",";
231 double latitudeDegrees = std::floor(latitude);
232 double latitudeMinutes = (latitude - latitudeDegrees) * 60.0;
233 double latitudeNmea = latitudeDegrees * 100.0 + latitudeMinutes;
235 double longitudeDegrees = std::floor(longitude);
236 double longitudeMinutes = (longitude - longitudeDegrees) * 60.0;
237 double longitudeNmea = longitudeDegrees * 100.0 + longitudeMinutes;
239 payloadStream << std::fixed << std::setprecision(6) << std::setw(10) << std::setfill(
'0') << latitudeNmea <<
",";
240 payloadStream << latitudeDirection <<
",";
241 payloadStream << std::fixed << std::setprecision(6) << std::setw(11) << std::setfill(
'0') << longitudeNmea <<
",";
242 payloadStream << longitudeDirection <<
",";
243 payloadStream << gpsQuality <<
",";
244 payloadStream << std::setw(2) << std::setfill(
'0') << satellites <<
",";
245 payloadStream << std::fixed << std::setprecision(1) << hdop <<
",";
246 payloadStream << std::fixed << std::setprecision(1) << altitude <<
",";
247 payloadStream << altitudeUnits <<
",";
249 if (geoidalSeparation == 0.0) {
250 payloadStream <<
",";
252 payloadStream << std::fixed << std::setprecision(1) << geoidalSeparation <<
",";
255 payloadStream << geoidalSeparationUnits <<
",";
257 if (dgpsAge == 0.0) {
258 payloadStream <<
",";
260 payloadStream << std::fixed << std::setprecision(1) << dgpsAge <<
",";
263 payloadStream << dgpsReferenceStationId;
265 std::string payload = payloadStream.str();
266 return "$" + payload +
"\r\n";
278 return latitudeDirection_;
286 return longitudeDirection_;
306 return altitudeUnits_;
310 return geoidalSeparation_;
314 return geoidalSeparationUnits_;
322 return dgpsReferenceStationId_;
Represents a parsed NMEA 0183 GGA (Global Positioning System Fix Data) sentence.
unsigned int getGpsQuality() const noexcept
Get GPS quality indicator.
double getLatitude() const noexcept
Get latitude in decimal degrees.
unsigned int getSatellites() const noexcept
Get number of satellites used.
std::unique_ptr< nmealib::Message > clone() const override
Create a polymorphic copy of this GGA message.
double getDgpsAge() const noexcept
Get age of DGPS data in seconds.
char getLongitudeDirection() const noexcept
Get longitude hemisphere indicator ('E' or 'W').
std::string getStringContent(bool verbose) const noexcept override
Return a human-readable string representation of this message.
char getAltitudeUnits() const noexcept
Get altitude units (typically 'M').
char getGeoidalSeparationUnits() const noexcept
Get geoidal separation units (typically 'M').
GGA(std::string talkerId, double timestamp, double latitude, char latitudeDirection, double longitude, char longitudeDirection, unsigned int gpsQuality, unsigned int satellites, double hdop, double altitude, char altitudeUnits, double geoidalSeparation, char geoidalSeparationUnits, double dgpsAge, std::string dgpsReferenceStationId)
Construct a GGA message from individual field values.
std::string getDgpsReferenceStationId() const noexcept
Get DGPS reference station identifier.
double getLongitude() const noexcept
Get longitude in decimal degrees.
char getLatitudeDirection() const noexcept
Get latitude hemisphere indicator ('N' or 'S').
double getGeoidalSeparation() const noexcept
Get geoidal separation value.
double getUtcTime() const noexcept
Get UTC fix time in hhmmss.ss numeric form.
bool operator==(const GGA &other) const noexcept
Compare two GGA messages for equality.
double getHdop() const noexcept
Get horizontal dilution of precision.
double getAltitude() const noexcept
Get altitude value.
Represents an NMEA 0183 sentence.
bool operator==(const Message0183 &other) const noexcept
Compares two Message0183 objects for equality based on their content and timestamp.
#define NMEALIB_RETURN_ERROR(exceptionExpr)
bool parseNmeaCoordinate(const std::string &text, double &value) noexcept
bool parseOptionalUnsigned(const std::string &text, unsigned int &value) noexcept
bool parseOptionalDouble(const std::string &text, double &value) noexcept