nmealib 0.0.4
NMEA 0183/NMEA 2000 parsing library
Loading...
Searching...
No Matches
gsa.cpp
Go to the documentation of this file.
2
5
6#include <iomanip>
7#include <sstream>
8#include <vector>
9
10namespace nmealib {
11namespace nmea0183 {
12
13std::unique_ptr<GSA> GSA::create(std::unique_ptr<Message0183> baseMessage) {
14 std::string context = "GSA::create";
15 if (baseMessage->getSentenceType() != "GSA") {
16 NMEALIB_RETURN_ERROR(NotGSAException(context, "Expected sentence type 'GSA', got " + baseMessage->getSentenceType()));
17 }
18
19 std::string payload = baseMessage->getPayload();
20 std::istringstream ss(payload);
21 std::string token;
22 std::vector<std::string> fields;
23
24 while (std::getline(ss, token, ',')) {
25 fields.push_back(token);
26 }
27
28 if (!payload.empty() && payload.back() == ',') {
29 fields.push_back("");
30 }
31
32 if (!fields.empty()) {
33 fields.erase(fields.begin());
34 }
35
36 if (fields.size() != 17 && fields.size() != 18) {
37 NMEALIB_RETURN_ERROR(NotGSAException(context, "Invalid fields in GSA payload: expected 17 or 18, got " + std::to_string(fields.size()) + ". Payload: " + payload));
38 }
39
40 char selectionMode = fields[0].empty() ? '\0' : fields[0][0];
41 unsigned int mode = 0U;
42 if (!detail::parseOptionalUnsigned(fields[1], mode)) {
43 NMEALIB_RETURN_ERROR(NmeaException(context, "Error parsing GSA fields"));
44 }
45
46 std::array<unsigned int, 12> satelliteIds{};
47 for (size_t index = 0; index < satelliteIds.size(); ++index) {
48 if (!detail::parseOptionalUnsigned(fields[2 + index], satelliteIds[index])) {
49 NMEALIB_RETURN_ERROR(NmeaException(context, "Error parsing GSA fields"));
50 }
51 }
52
53 double pdop = 0.0;
54 double hdop = 0.0;
55 double vdop = 0.0;
56 if (!detail::parseOptionalDouble(fields[14], pdop) ||
57 !detail::parseOptionalDouble(fields[15], hdop) ||
58 !detail::parseOptionalDouble(fields[16], vdop)) {
59 NMEALIB_RETURN_ERROR(NmeaException(context, "Error parsing GSA fields"));
60 }
61
62 std::optional<unsigned int> systemId = std::nullopt;
63 if (fields.size() == 18 && !fields[17].empty()) {
64 unsigned int parsedSystemId = 0U;
65 if (!detail::parseUnsigned(fields[17], parsedSystemId)) {
66 NMEALIB_RETURN_ERROR(NmeaException(context, "Error parsing GSA fields"));
67 }
68 systemId = parsedSystemId;
69 }
70
71 return std::unique_ptr<GSA>(new GSA(std::move(*baseMessage),
72 selectionMode,
73 mode,
74 satelliteIds,
75 pdop,
76 hdop,
77 vdop,
78 systemId));
79}
80
81GSA::GSA(Message0183 baseMessage,
82 char selectionMode,
83 unsigned int mode,
84 std::array<unsigned int, 12> satelliteIds,
85 double pdop,
86 double hdop,
87 double vdop,
88 std::optional<unsigned int> systemId) noexcept
89 : Message0183(std::move(baseMessage)),
90 selectionMode_(selectionMode),
91 mode_(mode),
92 satelliteIds_(satelliteIds),
93 pdop_(pdop),
94 hdop_(hdop),
95 vdop_(vdop),
96 systemId_(systemId) {}
97
98GSA::GSA(std::string talkerId,
99 char selectionMode,
100 unsigned int mode,
101 std::array<unsigned int, 12> satelliteIds,
102 double pdop,
103 double hdop,
104 double vdop,
105 std::optional<unsigned int> systemId)
106 : Message0183(*Message0183::create(composeRaw(talkerId,
107 selectionMode,
108 mode,
109 satelliteIds,
110 pdop,
111 hdop,
112 vdop,
113 systemId))),
114 selectionMode_(selectionMode),
115 mode_(mode),
116 satelliteIds_(satelliteIds),
117 pdop_(pdop),
118 hdop_(hdop),
119 vdop_(vdop),
120 systemId_(systemId) {}
121
122std::unique_ptr<nmealib::Message> GSA::clone() const {
123 return std::unique_ptr<GSA>(new GSA(*this));
124}
125
126std::string GSA::getStringContent(bool verbose) const noexcept {
127 std::ostringstream ss;
128 ss << this->toString(verbose);
129
130 if (verbose) {
131 ss << "\tSelection Mode: " << selectionMode_ << "\n";
132 ss << "\tMode: " << mode_ << "\n";
133 ss << "\tSatellites: ";
134
135 bool first = true;
136 for (unsigned int satelliteId : satelliteIds_) {
137 if (satelliteId == 0u) {
138 continue;
139 }
140 if (!first) {
141 ss << ",";
142 }
143 ss << satelliteId;
144 first = false;
145 }
146 if (first) {
147 ss << "None";
148 }
149
150 ss << "\n"
151 << "\tPDOP: " << pdop_ << "\n"
152 << "\tHDOP: " << hdop_ << "\n"
153 << "\tVDOP: " << vdop_;
154
155 if (systemId_.has_value()) {
156 ss << "\n"
157 << "\tSystem ID: " << systemId_.value();
158 }
159 ss << "\n";
160 } else {
161 ss << "SelectionMode=" << selectionMode_
162 << ", Mode=" << mode_
163 << ", PDOP=" << pdop_
164 << ", HDOP=" << hdop_
165 << ", VDOP=" << vdop_;
166 if (systemId_.has_value()) {
167 ss << ", SystemID=" << systemId_.value();
168 }
169 }
170
171 return ss.str();
172}
173
174std::string GSA::composeRaw(const std::string& talkerId,
175 char selectionMode,
176 unsigned int mode,
177 std::array<unsigned int, 12> satelliteIds,
178 double pdop,
179 double hdop,
180 double vdop,
181 std::optional<unsigned int> systemId) {
182 std::ostringstream payloadStream;
183 payloadStream << talkerId << "GSA,";
184 payloadStream << selectionMode << ",";
185 payloadStream << mode;
186
187 for (unsigned int satelliteId : satelliteIds) {
188 payloadStream << ",";
189 if (satelliteId != 0u) {
190 payloadStream << std::setw(2) << std::setfill('0') << satelliteId;
191 }
192 }
193
194 payloadStream << "," << std::fixed << std::setprecision(2) << pdop;
195 payloadStream << "," << std::fixed << std::setprecision(2) << hdop;
196 payloadStream << "," << std::fixed << std::setprecision(2) << vdop;
197
198 if (systemId.has_value()) {
199 payloadStream << "," << systemId.value();
200 }
201
202 std::string payload = payloadStream.str();
203 return "$" + payload + "\r\n";
204}
205
206char GSA::getSelectionMode() const noexcept {
207 return selectionMode_;
208}
209
210unsigned int GSA::getMode() const noexcept {
211 return mode_;
212}
213
214std::array<unsigned int, 12> GSA::getSatelliteIds() const noexcept {
215 return satelliteIds_;
216}
217
218unsigned int GSA::getSatelliteId(size_t index) const noexcept {
219 return index < satelliteIds_.size() ? satelliteIds_[index] : 0u;
220}
221
222double GSA::getPdop() const noexcept {
223 return pdop_;
224}
225
226double GSA::getHdop() const noexcept {
227 return hdop_;
228}
229
230double GSA::getVdop() const noexcept {
231 return vdop_;
232}
233
234bool GSA::hasSystemId() const noexcept {
235 return systemId_.has_value();
236}
237
238std::optional<unsigned int> GSA::getSystemId() const noexcept {
239 return systemId_;
240}
241
242bool GSA::operator==(const GSA& other) const noexcept {
243 return Message0183::operator==(other);
244}
245
246} // namespace nmea0183
247} // namespace nmealib
Represents a parsed NMEA 0183 GSA (GNSS DOP and Active Satellites) sentence.
Definition gsa.h:40
bool hasSystemId() const noexcept
Return whether an optional system ID is present.
Definition gsa.cpp:234
GSA(std::string talkerId, char selectionMode, unsigned int mode, std::array< unsigned int, 12 > satelliteIds, double pdop, double hdop, double vdop, std::optional< unsigned int > systemId=std::nullopt)
Construct a GSA message from individual field values.
Definition gsa.cpp:98
unsigned int getSatelliteId(size_t index) const noexcept
Get one satellite ID by slot index.
Definition gsa.cpp:218
double getVdop() const noexcept
Get VDOP value.
Definition gsa.cpp:230
std::unique_ptr< nmealib::Message > clone() const override
Create a polymorphic copy of this GSA message.
Definition gsa.cpp:122
std::optional< unsigned int > getSystemId() const noexcept
Get optional GNSS system ID.
Definition gsa.cpp:238
double getHdop() const noexcept
Get HDOP value.
Definition gsa.cpp:226
bool operator==(const GSA &other) const noexcept
Compare two GSA messages for equality.
Definition gsa.cpp:242
double getPdop() const noexcept
Get PDOP value.
Definition gsa.cpp:222
unsigned int getMode() const noexcept
Get fix dimension mode.
Definition gsa.cpp:210
std::array< unsigned int, 12 > getSatelliteIds() const noexcept
Get all 12 satellite ID slots (0 for empty).
Definition gsa.cpp:214
char getSelectionMode() const noexcept
Get selection mode indicator.
Definition gsa.cpp:206
std::string getStringContent(bool verbose) const noexcept override
Return a human-readable string representation of this message.
Definition gsa.cpp:126
Represents an NMEA 0183 sentence.
Definition nmea0183.h:98
bool operator==(const Message0183 &other) const noexcept
Compares two Message0183 objects for equality based on their content and timestamp.
Definition nmea0183.cpp:204
#define NMEALIB_RETURN_ERROR(exceptionExpr)
bool parseUnsigned(const std::string &text, T &value, int base=10) noexcept
Definition parse.h:15
bool parseOptionalUnsigned(const std::string &text, unsigned int &value) noexcept
Definition parse.h:102
bool parseOptionalDouble(const std::string &text, double &value) noexcept
Definition parse.h:86