nmealib 0.0.4
NMEA 0183/NMEA 2000 parsing library
Loading...
Searching...
No Matches
apb.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<APB> APB::create(std::unique_ptr<Message0183> baseMessage) {
14 std::string context = "APB::create";
15 if (baseMessage->getSentenceType() != "APB") {
16 NMEALIB_RETURN_ERROR(NotAPBException(context, "Expected sentence type 'APB', 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() != 14) {
37 NMEALIB_RETURN_ERROR(NotAPBException(context, "Invalid fields in APB payload: expected 14, got " + std::to_string(fields.size()) + ". Payload: " + payload));
38 }
39
40 double crossTrackErrorMagnitude = 0.0;
41 double bearingOriginToDestination = 0.0;
42 double bearingPresentToDestination = 0.0;
43 double headingToSteerToDestinationWaypoint = 0.0;
44 if (!detail::parseOptionalDouble(fields[2], crossTrackErrorMagnitude) ||
45 !detail::parseOptionalDouble(fields[7], bearingOriginToDestination) ||
46 !detail::parseOptionalDouble(fields[10], bearingPresentToDestination) ||
47 !detail::parseOptionalDouble(fields[12], headingToSteerToDestinationWaypoint)) {
48 NMEALIB_RETURN_ERROR(NmeaException(context, "Error parsing APB fields"));
49 }
50
51 char status1 = fields[0].empty() ? '\0' : fields[0][0];
52 char status2 = fields[1].empty() ? '\0' : fields[1][0];
53 char directionToSteer = fields[3].empty() ? '\0' : fields[3][0];
54 char crossTrackUnits = fields[4].empty() ? '\0' : fields[4][0];
55 char arrivalCircleStatus = fields[5].empty() ? '\0' : fields[5][0];
56 char perpendicularPassedAtWaypoint = fields[6].empty() ? '\0' : fields[6][0];
57 char bearingOriginToDestinationType = fields[8].empty() ? '\0' : fields[8][0];
58 std::string destinationWaypointId = fields[9];
59 char bearingPresentToDestinationType = fields[11].empty() ? '\0' : fields[11][0];
60 char headingToSteerToDestinationWaypointType = fields[13].empty() ? '\0' : fields[13][0];
61
62 return std::unique_ptr<APB>(new APB(std::move(*baseMessage),
63 status1,
64 status2,
65 crossTrackErrorMagnitude,
66 directionToSteer,
67 crossTrackUnits,
68 arrivalCircleStatus,
69 perpendicularPassedAtWaypoint,
70 bearingOriginToDestination,
71 bearingOriginToDestinationType,
72 destinationWaypointId,
73 bearingPresentToDestination,
74 bearingPresentToDestinationType,
75 headingToSteerToDestinationWaypoint,
76 headingToSteerToDestinationWaypointType));
77}
78
79APB::APB(Message0183 baseMessage,
80 char status1,
81 char status2,
82 double crossTrackErrorMagnitude,
83 char directionToSteer,
84 char crossTrackUnits,
85 char arrivalCircleStatus,
86 char perpendicularPassedAtWaypoint,
87 double bearingOriginToDestination,
88 char bearingOriginToDestinationType,
89 std::string destinationWaypointId,
90 double bearingPresentToDestination,
91 char bearingPresentToDestinationType,
92 double headingToSteerToDestinationWaypoint,
93 char headingToSteerToDestinationWaypointType) noexcept
94 : Message0183(std::move(baseMessage)),
95 status1_(status1),
96 status2_(status2),
97 crossTrackErrorMagnitude_(crossTrackErrorMagnitude),
98 directionToSteer_(directionToSteer),
99 crossTrackUnits_(crossTrackUnits),
100 arrivalCircleStatus_(arrivalCircleStatus),
101 perpendicularPassedAtWaypoint_(perpendicularPassedAtWaypoint),
102 bearingOriginToDestination_(bearingOriginToDestination),
103 bearingOriginToDestinationType_(bearingOriginToDestinationType),
104 destinationWaypointId_(std::move(destinationWaypointId)),
105 bearingPresentToDestination_(bearingPresentToDestination),
106 bearingPresentToDestinationType_(bearingPresentToDestinationType),
107 headingToSteerToDestinationWaypoint_(headingToSteerToDestinationWaypoint),
108 headingToSteerToDestinationWaypointType_(headingToSteerToDestinationWaypointType) {}
109
110APB::APB(std::string talkerId,
111 char status1,
112 char status2,
113 double crossTrackErrorMagnitude,
114 char directionToSteer,
115 char crossTrackUnits,
116 char arrivalCircleStatus,
117 char perpendicularPassedAtWaypoint,
118 double bearingOriginToDestination,
119 char bearingOriginToDestinationType,
120 std::string destinationWaypointId,
121 double bearingPresentToDestination,
122 char bearingPresentToDestinationType,
123 double headingToSteerToDestinationWaypoint,
124 char headingToSteerToDestinationWaypointType)
125 : Message0183(*Message0183::create(composeRaw(talkerId,
126 status1,
127 status2,
128 crossTrackErrorMagnitude,
129 directionToSteer,
130 crossTrackUnits,
131 arrivalCircleStatus,
132 perpendicularPassedAtWaypoint,
133 bearingOriginToDestination,
134 bearingOriginToDestinationType,
135 destinationWaypointId,
136 bearingPresentToDestination,
137 bearingPresentToDestinationType,
138 headingToSteerToDestinationWaypoint,
139 headingToSteerToDestinationWaypointType))),
140 status1_(status1),
141 status2_(status2),
142 crossTrackErrorMagnitude_(crossTrackErrorMagnitude),
143 directionToSteer_(directionToSteer),
144 crossTrackUnits_(crossTrackUnits),
145 arrivalCircleStatus_(arrivalCircleStatus),
146 perpendicularPassedAtWaypoint_(perpendicularPassedAtWaypoint),
147 bearingOriginToDestination_(bearingOriginToDestination),
148 bearingOriginToDestinationType_(bearingOriginToDestinationType),
149 destinationWaypointId_(std::move(destinationWaypointId)),
150 bearingPresentToDestination_(bearingPresentToDestination),
151 bearingPresentToDestinationType_(bearingPresentToDestinationType),
152 headingToSteerToDestinationWaypoint_(headingToSteerToDestinationWaypoint),
153 headingToSteerToDestinationWaypointType_(headingToSteerToDestinationWaypointType) {}
154
155std::unique_ptr<nmealib::Message> APB::clone() const {
156 return std::unique_ptr<APB>(new APB(*this));
157}
158
159std::string APB::getStringContent(bool verbose) const noexcept {
160 std::ostringstream ss;
161 ss << this->toString(verbose);
162 ss << std::fixed << std::setprecision(2);
163
164 if (verbose) {
165 ss << "\tStatus 1: " << status1_ << "\n";
166 ss << "\tStatus 2: " << status2_ << "\n";
167 ss << "\tCross Track Error Magnitude: " << crossTrackErrorMagnitude_ << "\n";
168 ss << "\tDirection to Steer: " << directionToSteer_ << "\n";
169 ss << "\tCross Track Units: " << crossTrackUnits_ << "\n";
170 ss << "\tArrival Circle Status: " << arrivalCircleStatus_ << "\n";
171 ss << "\tPerpendicular Passed at Waypoint: " << perpendicularPassedAtWaypoint_ << "\n";
172 ss << "\tBearing Origin->Destination: " << bearingOriginToDestination_ << " " << bearingOriginToDestinationType_ << "\n";
173 ss << "\tDestination Waypoint ID: " << destinationWaypointId_ << "\n";
174 ss << "\tBearing Present->Destination: " << bearingPresentToDestination_ << " " << bearingPresentToDestinationType_ << "\n";
175 ss << "\tHeading to Steer: " << headingToSteerToDestinationWaypoint_ << " " << headingToSteerToDestinationWaypointType_ << "\n";
176 } else {
177 ss << "Status1=" << status1_
178 << ", Status2=" << status2_
179 << ", XTE=" << crossTrackErrorMagnitude_ << crossTrackUnits_
180 << ", Steer=" << directionToSteer_
181 << ", Arrival=" << arrivalCircleStatus_
182 << ", Perpendicular=" << perpendicularPassedAtWaypoint_
183 << ", BOD=" << bearingOriginToDestination_ << bearingOriginToDestinationType_
184 << ", Dest=" << destinationWaypointId_
185 << ", BPD=" << bearingPresentToDestination_ << bearingPresentToDestinationType_
186 << ", Heading=" << headingToSteerToDestinationWaypoint_ << headingToSteerToDestinationWaypointType_;
187 }
188
189 return ss.str();
190}
191
192std::string APB::composeRaw(const std::string& talkerId,
193 char status1,
194 char status2,
195 double crossTrackErrorMagnitude,
196 char directionToSteer,
197 char crossTrackUnits,
198 char arrivalCircleStatus,
199 char perpendicularPassedAtWaypoint,
200 double bearingOriginToDestination,
201 char bearingOriginToDestinationType,
202 const std::string& destinationWaypointId,
203 double bearingPresentToDestination,
204 char bearingPresentToDestinationType,
205 double headingToSteerToDestinationWaypoint,
206 char headingToSteerToDestinationWaypointType) {
207 std::ostringstream payloadStream;
208 payloadStream << talkerId << "APB,";
209 payloadStream << status1 << ",";
210 payloadStream << status2 << ",";
211 payloadStream << std::fixed << std::setprecision(2) << crossTrackErrorMagnitude << ",";
212 payloadStream << directionToSteer << ",";
213 payloadStream << crossTrackUnits << ",";
214 payloadStream << arrivalCircleStatus << ",";
215 payloadStream << perpendicularPassedAtWaypoint << ",";
216 payloadStream << std::fixed << std::setprecision(3) << bearingOriginToDestination << ",";
217 payloadStream << bearingOriginToDestinationType << ",";
218 payloadStream << destinationWaypointId << ",";
219 payloadStream << std::fixed << std::setprecision(3) << bearingPresentToDestination << ",";
220 payloadStream << bearingPresentToDestinationType << ",";
221 payloadStream << std::fixed << std::setprecision(3) << headingToSteerToDestinationWaypoint << ",";
222 payloadStream << headingToSteerToDestinationWaypointType;
223
224 std::string payload = payloadStream.str();
225 return "$" + payload + "\r\n";
226}
227
228char APB::getStatus1() const noexcept {
229 return status1_;
230}
231
232char APB::getStatus2() const noexcept {
233 return status2_;
234}
235
236double APB::getCrossTrackErrorMagnitude() const noexcept {
237 return crossTrackErrorMagnitude_;
238}
239
240char APB::getDirectionToSteer() const noexcept {
241 return directionToSteer_;
242}
243
244char APB::getCrossTrackUnits() const noexcept {
245 return crossTrackUnits_;
246}
247
248char APB::getArrivalCircleStatus() const noexcept {
249 return arrivalCircleStatus_;
250}
251
253 return perpendicularPassedAtWaypoint_;
254}
255
256double APB::getBearingOriginToDestination() const noexcept {
257 return bearingOriginToDestination_;
258}
259
261 return bearingOriginToDestinationType_;
262}
263
264std::string APB::getDestinationWaypointId() const noexcept {
265 return destinationWaypointId_;
266}
267
268double APB::getBearingPresentToDestination() const noexcept {
269 return bearingPresentToDestination_;
270}
271
273 return bearingPresentToDestinationType_;
274}
275
277 return headingToSteerToDestinationWaypoint_;
278}
279
281 return headingToSteerToDestinationWaypointType_;
282}
283
284bool APB::operator==(const APB& other) const noexcept {
285 return Message0183::operator==(other);
286}
287
288} // namespace nmea0183
289} // namespace nmealib
Represents a parsed NMEA 0183 APB (Autopilot Sentence "B") sentence.
Definition apb.h:37
char getHeadingToSteerToDestinationWaypointType() const noexcept
Get heading type for heading-to-steer ('M' or 'T').
Definition apb.cpp:280
double getBearingOriginToDestination() const noexcept
Get bearing from origin to destination.
Definition apb.cpp:256
char getBearingPresentToDestinationType() const noexcept
Get bearing type for present-to-destination ('M' or 'T').
Definition apb.cpp:272
double getHeadingToSteerToDestinationWaypoint() const noexcept
Get heading to steer to destination waypoint.
Definition apb.cpp:276
APB(std::string talkerId, char status1, char status2, double crossTrackErrorMagnitude, char directionToSteer, char crossTrackUnits, char arrivalCircleStatus, char perpendicularPassedAtWaypoint, double bearingOriginToDestination, char bearingOriginToDestinationType, std::string destinationWaypointId, double bearingPresentToDestination, char bearingPresentToDestinationType, double headingToSteerToDestinationWaypoint, char headingToSteerToDestinationWaypointType)
Construct an APB message from individual field values.
Definition apb.cpp:110
char getStatus1() const noexcept
Get primary APB status flag.
Definition apb.cpp:228
char getCrossTrackUnits() const noexcept
Get cross-track units indicator.
Definition apb.cpp:244
double getCrossTrackErrorMagnitude() const noexcept
Get cross-track error magnitude in nautical miles.
Definition apb.cpp:236
char getBearingOriginToDestinationType() const noexcept
Get bearing type for origin-to-destination ('M' or 'T').
Definition apb.cpp:260
char getArrivalCircleStatus() const noexcept
Get arrival circle status flag.
Definition apb.cpp:248
std::unique_ptr< nmealib::Message > clone() const override
Create a polymorphic copy of this APB message.
Definition apb.cpp:155
bool operator==(const APB &other) const noexcept
Compare two APB messages for equality.
Definition apb.cpp:284
char getPerpendicularPassedAtWaypoint() const noexcept
Get perpendicular-passed status flag.
Definition apb.cpp:252
double getBearingPresentToDestination() const noexcept
Get bearing from present position to destination.
Definition apb.cpp:268
std::string getStringContent(bool verbose) const noexcept override
Return a human-readable string representation of this message.
Definition apb.cpp:159
char getStatus2() const noexcept
Get secondary APB status flag.
Definition apb.cpp:232
std::string getDestinationWaypointId() const noexcept
Get destination waypoint identifier.
Definition apb.cpp:264
char getDirectionToSteer() const noexcept
Get steering direction indicator ('L' or 'R').
Definition apb.cpp:240
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 parseOptionalDouble(const std::string &text, double &value) noexcept
Definition parse.h:86