nmealib 0.0.4
NMEA 0183/NMEA 2000 parsing library
Loading...
Searching...
No Matches
xdr.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<XDR> XDR::create(std::unique_ptr<Message0183> baseMessage) {
14 std::string context = "XDR::create";
15 if (baseMessage->getSentenceType() != "XDR") {
16 NMEALIB_RETURN_ERROR(NotXDRException(context, "Expected sentence type 'XDR', 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.empty() || (fields.size() % 4) != 0) {
37 NMEALIB_RETURN_ERROR(NotXDRException(context, "Invalid fields in XDR payload: expected one or more quadruplets, got " + std::to_string(fields.size()) + " fields. Payload: " + payload));
38 }
39
40 std::vector<TransducerMeasurement> transducers;
41 transducers.reserve(fields.size() / 4);
42
43 for (std::size_t index = 0; index < fields.size(); index += 4) {
44 TransducerMeasurement measurement;
45 measurement.transducerType = fields[index].empty() ? '\0' : fields[index][0];
46 if (!detail::parseOptionalDouble(fields[index + 1], measurement.measurement)) {
47 NMEALIB_RETURN_ERROR(NmeaException(context, "Error parsing XDR fields"));
48 }
49 measurement.units = fields[index + 2].empty() ? '\0' : fields[index + 2][0];
50 measurement.name = fields[index + 3];
51 transducers.push_back(std::move(measurement));
52 }
53
54 return std::unique_ptr<XDR>(new XDR(std::move(*baseMessage), std::move(transducers)));
55}
56
57XDR::XDR(Message0183 baseMessage, std::vector<TransducerMeasurement> transducers) noexcept
58 : Message0183(std::move(baseMessage)),
59 transducers_(std::move(transducers)) {}
60
61XDR::XDR(std::string talkerId, std::vector<TransducerMeasurement> transducers)
62 : Message0183(*Message0183::create(composeRaw(talkerId, transducers))),
63 transducers_(std::move(transducers)) {}
64
65std::unique_ptr<nmealib::Message> XDR::clone() const {
66 return std::unique_ptr<XDR>(new XDR(*this));
67}
68
69std::string XDR::getStringContent(bool verbose) const noexcept {
70 std::ostringstream ss;
71 ss << this->toString(verbose);
72
73 if (verbose) {
74 ss << "\tTransducers: " << transducers_.size() << "\n";
75 for (std::size_t index = 0; index < transducers_.size(); ++index) {
76 const auto& transducer = transducers_[index];
77 ss << "\t[" << index << "] Type=" << transducer.transducerType
78 << ", Value=" << transducer.measurement
79 << ", Units=" << transducer.units
80 << ", Name=" << transducer.name << "\n";
81 }
82 } else {
83 ss << "Transducers=" << transducers_.size();
84 }
85
86 return ss.str();
87}
88
89std::string XDR::composeRaw(const std::string& talkerId,
90 const std::vector<TransducerMeasurement>& transducers) {
91 std::ostringstream payloadStream;
92 payloadStream << talkerId << "XDR";
93
94 payloadStream << std::setprecision(15);
95 for (const auto& transducer : transducers) {
96 payloadStream << ",";
97 if (transducer.transducerType != '\0') {
98 payloadStream << transducer.transducerType;
99 }
100 payloadStream << ",";
101 payloadStream << transducer.measurement;
102 payloadStream << ",";
103 if (transducer.units != '\0') {
104 payloadStream << transducer.units;
105 }
106 payloadStream << ",";
107 payloadStream << transducer.name;
108 }
109
110 std::string payload = payloadStream.str();
111 return "$" + payload + "\r\n";
112}
113
114const std::vector<XDR::TransducerMeasurement>& XDR::getTransducers() const noexcept {
115 return transducers_;
116}
117
118std::size_t XDR::getTransducerCount() const noexcept {
119 return transducers_.size();
120}
121
122const XDR::TransducerMeasurement* XDR::getTransducer(std::size_t index) const noexcept {
123 if (index >= transducers_.size()) {
124 return nullptr;
125 }
126 return &transducers_[index];
127}
128
129bool XDR::operator==(const XDR& other) const noexcept {
130 return Message0183::operator==(other);
131}
132
133} // namespace nmea0183
134} // 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 XDR (Transducer Measurement) sentence.
Definition xdr.h:43
std::size_t getTransducerCount() const noexcept
Get the number of transducer measurements in this sentence.
Definition xdr.cpp:118
bool operator==(const XDR &other) const noexcept
Compare two XDR messages for equality.
Definition xdr.cpp:129
const std::vector< TransducerMeasurement > & getTransducers() const noexcept
Get all transducer measurements in this sentence.
Definition xdr.cpp:114
std::string getStringContent(bool verbose) const noexcept override
Return a human-readable string representation of this message.
Definition xdr.cpp:69
std::unique_ptr< nmealib::Message > clone() const override
Create a polymorphic copy of this XDR message.
Definition xdr.cpp:65
XDR(std::string talkerId, std::vector< TransducerMeasurement > transducers)
Construct an XDR message from field values.
Definition xdr.cpp:61
const TransducerMeasurement * getTransducer(std::size_t index) const noexcept
Get a transducer measurement by index.
Definition xdr.cpp:122
#define NMEALIB_RETURN_ERROR(exceptionExpr)
bool parseOptionalDouble(const std::string &text, double &value) noexcept
Definition parse.h:86
One transducer measurement quadruplet in an XDR sentence.
Definition xdr.h:48