nmealib 0.0.4
NMEA 0183/NMEA 2000 parsing library
Loading...
Searching...
No Matches
xte.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<XTE> XTE::create(std::unique_ptr<Message0183> baseMessage) {
14 std::string context = "XTE::create";
15 if (baseMessage->getSentenceType() != "XTE") {
16 NMEALIB_RETURN_ERROR(NotXTEException(context, "Expected sentence type 'XTE', 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() != 5 && fields.size() != 6) {
37 NMEALIB_RETURN_ERROR(NotXTEException(context, "Invalid fields in XTE payload: expected 5 or 6, got " + std::to_string(fields.size()) + ". Payload: " + payload));
38 }
39
40 char status1 = fields[0].empty() ? '\0' : fields[0][0];
41 char status2 = fields[1].empty() ? '\0' : fields[1][0];
42 double crossTrackError = 0.0;
43 if (!detail::parseOptionalDouble(fields[2], crossTrackError)) {
44 NMEALIB_RETURN_ERROR(NmeaException(context, "Error parsing cross-track error field"));
45 }
46 char steerDirection = fields[3].empty() ? '\0' : fields[3][0];
47 char crossTrackUnits = fields[4].empty() ? '\0' : fields[4][0];
48 std::optional<char> faaModeIndicator = std::nullopt;
49 if (fields.size() == 6 && !fields[5].empty()) {
50 faaModeIndicator = fields[5][0];
51 }
52
53 return std::unique_ptr<XTE>(new XTE(std::move(*baseMessage),
54 status1,
55 status2,
56 crossTrackError,
57 steerDirection,
58 crossTrackUnits,
59 faaModeIndicator));
60}
61
62XTE::XTE(Message0183 baseMessage,
63 char status1,
64 char status2,
65 double crossTrackError,
66 char steerDirection,
67 char crossTrackUnits,
68 std::optional<char> faaModeIndicator) noexcept
69 : Message0183(std::move(baseMessage)),
70 status1_(status1),
71 status2_(status2),
72 crossTrackError_(crossTrackError),
73 steerDirection_(steerDirection),
74 crossTrackUnits_(crossTrackUnits),
75 faaModeIndicator_(faaModeIndicator) {}
76
77XTE::XTE(std::string talkerId,
78 char status1,
79 char status2,
80 double crossTrackError,
81 char steerDirection,
82 char crossTrackUnits,
83 std::optional<char> faaModeIndicator)
84 : Message0183(*Message0183::create(composeRaw(talkerId,
85 status1,
86 status2,
87 crossTrackError,
88 steerDirection,
89 crossTrackUnits,
90 faaModeIndicator))),
91 status1_(status1),
92 status2_(status2),
93 crossTrackError_(crossTrackError),
94 steerDirection_(steerDirection),
95 crossTrackUnits_(crossTrackUnits),
96 faaModeIndicator_(faaModeIndicator) {}
97
98std::unique_ptr<nmealib::Message> XTE::clone() const {
99 return std::unique_ptr<XTE>(new XTE(*this));
100}
101
102std::string XTE::getStringContent(bool verbose) const noexcept {
103 std::ostringstream ss;
104 ss << this->toString(verbose);
105 ss << std::fixed << std::setprecision(2);
106
107 if (verbose) {
108 ss << "\tStatus1: " << status1_ << "\n";
109 ss << "\tStatus2: " << status2_ << "\n";
110 ss << "\tCross Track Error: " << crossTrackError_ << " " << crossTrackUnits_ << "\n";
111 ss << "\tSteer Direction: " << steerDirection_;
112 if (faaModeIndicator_.has_value()) {
113 ss << "\n\tFAA Mode Indicator: " << faaModeIndicator_.value();
114 }
115 ss << "\n";
116 } else {
117 ss << "Status1=" << status1_
118 << ", Status2=" << status2_
119 << ", XTE=" << crossTrackError_ << crossTrackUnits_
120 << ", Steer=" << steerDirection_;
121 if (faaModeIndicator_.has_value()) {
122 ss << ", FAA=" << faaModeIndicator_.value();
123 }
124 }
125
126 return ss.str();
127}
128
129std::string XTE::composeRaw(const std::string& talkerId,
130 char status1,
131 char status2,
132 double crossTrackError,
133 char steerDirection,
134 char crossTrackUnits,
135 std::optional<char> faaModeIndicator) {
136 std::ostringstream payloadStream;
137 payloadStream << talkerId << "XTE,";
138 if (status1 != '\0') {
139 payloadStream << status1;
140 }
141 payloadStream << ",";
142 if (status2 != '\0') {
143 payloadStream << status2;
144 }
145 payloadStream << ",";
146 payloadStream << std::fixed << std::setprecision(1) << crossTrackError << ",";
147 if (steerDirection != '\0') {
148 payloadStream << steerDirection;
149 }
150 payloadStream << ",";
151 if (crossTrackUnits != '\0') {
152 payloadStream << crossTrackUnits;
153 }
154 if (faaModeIndicator.has_value()) {
155 payloadStream << "," << faaModeIndicator.value();
156 }
157
158 std::string payload = payloadStream.str();
159 return "$" + payload + "\r\n";
160}
161
162char XTE::getStatus1() const noexcept {
163 return status1_;
164}
165
166char XTE::getStatus2() const noexcept {
167 return status2_;
168}
169
170double XTE::getCrossTrackError() const noexcept {
171 return crossTrackError_;
172}
173
174char XTE::getSteerDirection() const noexcept {
175 return steerDirection_;
176}
177
178char XTE::getCrossTrackUnits() const noexcept {
179 return crossTrackUnits_;
180}
181
182bool XTE::hasFaaModeIndicator() const noexcept {
183 return faaModeIndicator_.has_value();
184}
185
186std::optional<char> XTE::getFaaModeIndicator() const noexcept {
187 return faaModeIndicator_;
188}
189
190bool XTE::operator==(const XTE& other) const noexcept {
191 return Message0183::operator==(other) &&
192 status1_ == other.status1_ &&
193 status2_ == other.status2_ &&
194 crossTrackError_ == other.crossTrackError_ &&
195 steerDirection_ == other.steerDirection_ &&
196 crossTrackUnits_ == other.crossTrackUnits_ &&
197 faaModeIndicator_ == other.faaModeIndicator_;
198}
199
200} // namespace nmea0183
201} // namespace nmealib
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
Represents a parsed NMEA 0183 XTE (Cross-Track Error, Measured) sentence.
Definition xte.h:44
char getStatus1() const noexcept
Get the first status field.
Definition xte.cpp:162
double getCrossTrackError() const noexcept
Get the cross-track error magnitude in nautical miles.
Definition xte.cpp:170
char getCrossTrackUnits() const noexcept
Get the cross-track units indicator (typically 'N').
Definition xte.cpp:178
std::optional< char > getFaaModeIndicator() const noexcept
Get optional FAA mode indicator.
Definition xte.cpp:186
bool operator==(const XTE &other) const noexcept
Compare two XTE messages for equality.
Definition xte.cpp:190
std::unique_ptr< nmealib::Message > clone() const override
Create a polymorphic copy of this XTE message.
Definition xte.cpp:98
char getSteerDirection() const noexcept
Get the steer direction indicator ('L' or 'R').
Definition xte.cpp:174
char getStatus2() const noexcept
Get the second status field.
Definition xte.cpp:166
std::string getStringContent(bool verbose) const noexcept override
Return a human-readable string representation of this message.
Definition xte.cpp:102
bool hasFaaModeIndicator() const noexcept
Return whether FAA mode indicator is present.
Definition xte.cpp:182
XTE(std::string talkerId, char status1, char status2, double crossTrackError, char steerDirection, char crossTrackUnits, std::optional< char > faaModeIndicator=std::nullopt)
Construct an XTE message from individual field values.
Definition xte.cpp:77
#define NMEALIB_RETURN_ERROR(exceptionExpr)
bool parseOptionalDouble(const std::string &text, double &value) noexcept
Definition parse.h:86