21 std::string sentenceType,
22 std::string payload) noexcept
23 : Message(std::move(raw), Type::NMEA0183, ts),
24 startChar_(startChar),
25 talker_(std::move(talker)),
26 sentenceType_(std::move(sentenceType)),
27 payload_(std::move(payload)) {
28 calculatedChecksumStr_ = computeChecksum(payload_);
35 std::string sentenceType,
37 std::string checksumStr) noexcept
38 : Message(std::move(raw), Type::NMEA0183, ts),
39 startChar_(startChar),
40 talker_(std::move(talker)),
41 sentenceType_(std::move(sentenceType)),
42 payload_(std::move(payload)),
43 checksumStr_(std::move(checksumStr)) {
44 calculatedChecksumStr_ = computeChecksum(payload_);
48 std::string context =
"Message0183::create";
49#if defined(NMEALIB_NO_EXCEPTIONS)
50 if (!validateFormat(context, raw)) {
54 validateFormat(context, raw);
57 char startChar = raw[0];
59 bool hasCRLF = raw.size() >= 2 && raw.substr(raw.size() - 2) ==
"\r\n";
62 std::string talker = raw.substr(1, 2);
63 std::string sentenceType = raw.substr(3, 3);
64 bool hasChecksum = raw.find(
'*') != std::string::npos;
66 size_t asteriskPos = raw.find(
'*');
67 std::string payload = raw.substr(1, asteriskPos - 1);
68 std::string checksumStr = raw.substr(asteriskPos + 1, 2);
69 return std::unique_ptr<Message0183>(
new Message0183(raw, ts, startChar, talker, sentenceType, payload, checksumStr));
72 std::string payload = raw.substr(1, raw.size() - 3);
73 return std::unique_ptr<Message0183>(
new Message0183(raw, ts, startChar, talker, sentenceType, payload));
75 std::string payload = raw.substr(1);
76 return std::unique_ptr<Message0183>(
new Message0183(raw, ts, startChar, talker, sentenceType, payload));
81bool Message0183::validateFormat(
const std::string& context,
const std::string& raw) {
88 if(raw.empty() || (raw[0] !=
'$' && raw[0] !=
'!')) {
92 bool hasChecksum = raw.find(
'*') != std::string::npos;
95 size_t asteriskPos = raw.find(
'*');
96 std::string checksumStr = raw.substr(asteriskPos + 1, 2);
97 if(!isHexByte(checksumStr)) {
106 return std::unique_ptr<Message0183>(
new Message0183(*
this));
137 std::stringstream ss;
139 ss << this->toString(verbose);
141 if (verbose) ss <<
"\tUnimplemented sentence type";
142 else ss <<
"Unimplemented sentence type";
148 std::stringstream ss;
149 std::string validity =
"KO";
155 ss <<
"--------------------------------\n";
156 ss <<
"Protocol: " << typeToString(type_) <<
"\n";
157 ss <<
"Talker: " << getTalker() <<
"\n";
158 ss <<
"Sentence Type: " << getSentenceType() <<
"\n";
159 ss <<
"Checksum: " << (checksumStr_.empty() ?
"None" : validity) <<
"\n";
162 ss <<
"[" << validity <<
"] " << typeToString(type_) <<
" " << getTalker() <<
" " << getSentenceType() <<
": ";
180std::string Message0183::computeChecksum(
const std::string& payload)
noexcept {
181 uint8_t checksum = std::accumulate(payload.begin(), payload.end(),
static_cast<uint8_t
>(0),
182 [](uint8_t acc,
char c) { return acc ^ static_cast<uint8_t>(c); });
183 std::stringstream ss;
184 ss << std::uppercase << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(checksum);
188bool Message0183::isHexByte(
const std::string& s)
noexcept {
189 if (s.size() != 2)
return false;
190 return std::isxdigit(
static_cast<unsigned char>(s[0])) &&
191 std::isxdigit(
static_cast<unsigned char>(s[1]));
195 double converted = 0.0;
205 return startChar_ == other.startChar_ &&
206 talker_ == other.talker_ &&
207 sentenceType_ == other.sentenceType_ &&
208 payload_ == other.payload_ &&
209 checksumStr_ == other.checksumStr_ &&
210 calculatedChecksumStr_ == other.calculatedChecksumStr_ &&
std::chrono::system_clock::time_point TimePoint
bool operator==(const Message &other) const noexcept
Compares two Message objects for equality based on their content.
Base exception class for all NMEA library errors.
Represents an NMEA 0183 sentence.
bool validate() const noexcept override
Returns whether the message is valid or not.
std::string serialize() const override
Returns the wire-format representation of the NMEA 0183 sentence, that is, the raw information that w...
std::string getChecksumStr() const
Get the checksum string extracted from the raw sentence.
std::string getSentenceType() const noexcept
Returns the sentence type identifier extracted from the sentence.
virtual std::string getStringContent(bool verbose) const noexcept
Returns a human-readable string representation of the message content.
bool operator==(const Message0183 &other) const noexcept
Compares two Message0183 objects for equality based on their content and timestamp.
std::unique_ptr< nmealib::Message > clone() const override
Creates a polymorphic deep copy of this Message0183.
std::string calculatedChecksumStr_
std::string getTalker() const noexcept
Returns the talker identifier extracted from the sentence.
std::string getPayload() const noexcept
Returns the payload of the NMEA 0183 sentence.
static double convertNmeaCoordinateToDecimalDegrees(const std::string &nmeaCoordinate)
Converts an NMEA coordinate in ddmm.mmmm / dddmm.mmmm format to decimal degrees.
Message0183(const Message0183 &)=default
Copy constructor.
char getStartChar() const noexcept
Returns the start character of the NMEA 0183 sentence.
std::string sentenceType_
std::string getCalculatedChecksumStr() const noexcept
Get the calculated checksum string for the sentence payload.
std::string toString(bool verbose) const noexcept
Provides the common string representation for every NMEA 0183 message, which can be used by derived c...
static std::unique_ptr< Message0183 > create(const std::string &raw, TimePoint ts=std::chrono::system_clock::now())
Protected factory method to create a Message0183 from a raw sentence string.
Exception thrown when an operation requires a checksum but none is present in the sentence.
#define NMEALIB_RETURN_ERROR_VALUE(exceptionExpr, value)
bool parseNmeaCoordinate(const std::string &text, double &value) noexcept