13std::unique_ptr<VLW> VLW::create(std::unique_ptr<Message0183> baseMessage) {
14 std::string context =
"VLW::create";
15 if (baseMessage->getSentenceType() !=
"VLW") {
16 NMEALIB_RETURN_ERROR(NotVLWException(context,
"Expected sentence type 'VLW', got " + baseMessage->getSentenceType()));
19 std::string payload = baseMessage->getPayload();
20 std::istringstream ss(payload);
22 std::vector<std::string> fields;
24 while (std::getline(ss, token,
',')) {
25 fields.push_back(token);
28 if (!payload.empty() && payload.back() ==
',') {
32 if (!fields.empty()) {
33 fields.erase(fields.begin());
36 if (fields.size() != 4 && fields.size() != 8) {
37 NMEALIB_RETURN_ERROR(NotVLWException(context,
"Invalid fields in VLW payload: expected 4 or 8, got " + std::to_string(fields.size()) +
". Payload: " + payload));
40 double totalWaterDistanceNm = 0.0;
41 double waterDistanceSinceResetNm = 0.0;
47 char totalWaterDistanceUnit = fields[1].empty() ?
'\0' : fields[1][0];
48 char waterDistanceSinceResetUnit = fields[3].empty() ?
'\0' : fields[3][0];
50 bool hasGroundDistanceFields = fields.size() == 8;
51 double totalGroundDistanceNm = 0.0;
52 char totalGroundDistanceUnit =
'\0';
53 double groundDistanceSinceResetNm = 0.0;
54 char groundDistanceSinceResetUnit =
'\0';
56 if (hasGroundDistanceFields) {
62 totalGroundDistanceUnit = fields[5].empty() ?
'\0' : fields[5][0];
63 groundDistanceSinceResetUnit = fields[7].empty() ?
'\0' : fields[7][0];
66 return std::unique_ptr<VLW>(
new VLW(std::move(*baseMessage),
68 totalWaterDistanceUnit,
69 waterDistanceSinceResetNm,
70 waterDistanceSinceResetUnit,
71 hasGroundDistanceFields,
72 totalGroundDistanceNm,
73 totalGroundDistanceUnit,
74 groundDistanceSinceResetNm,
75 groundDistanceSinceResetUnit));
78VLW::VLW(Message0183 baseMessage,
79 double totalWaterDistanceNm,
80 char totalWaterDistanceUnit,
81 double waterDistanceSinceResetNm,
82 char waterDistanceSinceResetUnit,
83 bool hasGroundDistanceData,
84 double totalGroundDistanceNm,
85 char totalGroundDistanceUnit,
86 double groundDistanceSinceResetNm,
87 char groundDistanceSinceResetUnit) noexcept
88 : Message0183(std::move(baseMessage)),
89 totalWaterDistanceNm_(totalWaterDistanceNm),
90 totalWaterDistanceUnit_(totalWaterDistanceUnit),
91 waterDistanceSinceResetNm_(waterDistanceSinceResetNm),
92 waterDistanceSinceResetUnit_(waterDistanceSinceResetUnit),
93 hasGroundDistanceData_(hasGroundDistanceData),
94 totalGroundDistanceNm_(totalGroundDistanceNm),
95 totalGroundDistanceUnit_(totalGroundDistanceUnit),
96 groundDistanceSinceResetNm_(groundDistanceSinceResetNm),
97 groundDistanceSinceResetUnit_(groundDistanceSinceResetUnit) {}
99VLW::VLW(std::string talkerId,
100 double totalWaterDistanceNm,
101 double waterDistanceSinceResetNm,
102 std::optional<double> totalGroundDistanceNm,
103 std::optional<double> groundDistanceSinceResetNm)
105 totalWaterDistanceNm,
106 waterDistanceSinceResetNm,
107 totalGroundDistanceNm,
108 groundDistanceSinceResetNm))),
109 totalWaterDistanceNm_(totalWaterDistanceNm),
110 totalWaterDistanceUnit_(
'N'),
111 waterDistanceSinceResetNm_(waterDistanceSinceResetNm),
112 waterDistanceSinceResetUnit_(
'N'),
113 hasGroundDistanceData_(totalGroundDistanceNm.has_value() && groundDistanceSinceResetNm.has_value()),
114 totalGroundDistanceNm_(totalGroundDistanceNm.value_or(0.0)),
115 totalGroundDistanceUnit_(hasGroundDistanceData_ ?
'N' :
'\0'),
116 groundDistanceSinceResetNm_(groundDistanceSinceResetNm.value_or(0.0)),
117 groundDistanceSinceResetUnit_(hasGroundDistanceData_ ?
'N' :
'\0') {}
120 return std::unique_ptr<VLW>(
new VLW(*
this));
124 std::ostringstream ss;
125 ss << this->toString(verbose);
126 ss << std::fixed << std::setprecision(2);
129 ss <<
"\tTotal Water Distance: " << totalWaterDistanceNm_ <<
" " << totalWaterDistanceUnit_ <<
"\n";
130 ss <<
"\tWater Distance Since Reset: " << waterDistanceSinceResetNm_ <<
" " << waterDistanceSinceResetUnit_;
131 if (hasGroundDistanceData_) {
133 <<
"\tTotal Ground Distance: " << totalGroundDistanceNm_ <<
" " << totalGroundDistanceUnit_ <<
"\n"
134 <<
"\tGround Distance Since Reset: " << groundDistanceSinceResetNm_ <<
" " << groundDistanceSinceResetUnit_;
138 ss <<
"WaterTotal=" << totalWaterDistanceNm_
139 <<
", WaterReset=" << waterDistanceSinceResetNm_;
140 if (hasGroundDistanceData_) {
141 ss <<
", GroundTotal=" << totalGroundDistanceNm_
142 <<
", GroundReset=" << groundDistanceSinceResetNm_;
149std::string VLW::composeRaw(
const std::string& talkerId,
150 double totalWaterDistanceNm,
151 double waterDistanceSinceResetNm,
152 std::optional<double> totalGroundDistanceNm,
153 std::optional<double> groundDistanceSinceResetNm) {
154 const bool hasGroundDistanceFields = totalGroundDistanceNm.has_value() && groundDistanceSinceResetNm.has_value();
156 std::ostringstream payloadStream;
157 payloadStream << talkerId <<
"VLW,";
158 payloadStream << std::fixed << std::setprecision(1) << totalWaterDistanceNm <<
",N,";
159 payloadStream << std::fixed << std::setprecision(1) << waterDistanceSinceResetNm <<
",N";
161 if (hasGroundDistanceFields) {
162 payloadStream <<
",";
163 payloadStream << std::fixed << std::setprecision(1) << totalGroundDistanceNm.value() <<
",N,";
164 payloadStream << std::fixed << std::setprecision(1) << groundDistanceSinceResetNm.value() <<
",N";
167 std::string payload = payloadStream.str();
168 return "$" + payload +
"\r\n";
172 return totalWaterDistanceNm_;
176 return totalWaterDistanceUnit_;
180 return waterDistanceSinceResetNm_;
184 return waterDistanceSinceResetUnit_;
188 return hasGroundDistanceData_;
192 return totalGroundDistanceNm_;
196 return totalGroundDistanceUnit_;
200 return groundDistanceSinceResetNm_;
204 return groundDistanceSinceResetUnit_;
Represents an NMEA 0183 sentence.
bool operator==(const Message0183 &other) const noexcept
Compares two Message0183 objects for equality based on their content and timestamp.
char getTotalWaterDistanceUnit() const noexcept
double getWaterDistanceSinceResetNm() const noexcept
std::unique_ptr< nmealib::Message > clone() const override
Creates a polymorphic deep copy of this Message0183.
char getWaterDistanceSinceResetUnit() const noexcept
char getTotalGroundDistanceUnit() const noexcept
VLW(std::string talkerId, double totalWaterDistanceNm, double waterDistanceSinceResetNm, std::optional< double > totalGroundDistanceNm=std::nullopt, std::optional< double > groundDistanceSinceResetNm=std::nullopt)
double getTotalGroundDistanceNm() const noexcept
std::string getStringContent(bool verbose) const noexcept override
Returns a human-readable string representation of the message content.
bool hasGroundDistanceData() const noexcept
char getGroundDistanceSinceResetUnit() const noexcept
double getTotalWaterDistanceNm() const noexcept
double getGroundDistanceSinceResetNm() const noexcept
bool operator==(const VLW &other) const noexcept
#define NMEALIB_RETURN_ERROR(exceptionExpr)
bool parseOptionalDouble(const std::string &text, double &value) noexcept