36static bool Is0183ChecksumOk(
const std::string& sentence) {
37 const size_t cs_start = sentence.find(
'*');
38 if (cs_start == std::string::npos || cs_start > sentence.size() - 3)
41 const std::string cs_str = sentence.substr(cs_start + 1, 2);
42 const unsigned long checksum = strtol(cs_str.c_str(),
nullptr, 16);
43 if (checksum == 0L && cs_str !=
"00")
return false;
45 unsigned char calculated_checksum = 0;
46 for (
const char c : sentence.substr(1, cs_start - 1))
47 calculated_checksum ^= static_cast<unsigned char>(c);
48 return calculated_checksum == checksum;
57static std::string GetPayloadSentence(
const std::string& sentence) {
58 size_t start_pos = sentence.find(
'$');
59 if (start_pos == std::string::npos) start_pos = sentence.find(
'!');
60 if (start_pos == std::string::npos)
return "";
61 if (sentence.size() < start_pos + 6)
return "";
62 return sentence.substr(start_pos);
67CommDriverN0183::CommDriverN0183(NavAddr::Bus,
const std::string& s)
70CommDriverN0183::~CommDriverN0183() =
default;
75 const std::string sentence = GetPayloadSentence(payload);
76 if (sentence.empty())
return;
77 assert(sentence[0] ==
'$' || sentence[0] ==
'!');
78 assert(sentence.size() >= 6);
80 const bool is_garbage =
81 sentence.size() > 128 ||
82 std::any_of(sentence.begin(), sentence.end(),
83 [](
char c) { return !isprint(c) && c !=
'\n' && c !=
'\r'; });
84 const bool has_checksum =
85 sentence.find(
'*', sentence.size() - 6) != std::string::npos;
89 state = NavMsg::State::kCannotParse;
90 else if (!params.SentencePassesFilter(sentence, FILTER_INPUT))
91 state = NavMsg::State::kFiltered;
92 else if (has_checksum && !Is0183ChecksumOk(sentence))
93 state = NavMsg::State::kBadChecksum;
95 state = NavMsg::State::kOk;
98 state == NavMsg::State::kCannotParse ?
"TRASH" : sentence.substr(1, 5);
100 std::make_shared<const Nmea0183Msg>(
id, sentence, GetAddress(), state);
102 auto msg = std::make_shared<const Nmea0183Msg>(
"TRASH", payload,
103 GetAddress(), state);
104 listener.
Notify(std::move(msg));
107 const std::string
id = sentence.substr(1, 5);
109 std::make_shared<const Nmea0183Msg>(
id, sentence, GetAddress(), state);
110 listener.
Notify(std::move(msg));
Common interface for all drivers.
void SendToListener(const std::string &payload, DriverListener &listener, const ConnectionParams ¶ms)
Wrap argument string in NavMsg pointer, forward to listener.
Interface for handling incoming messages.
virtual void Notify(std::shared_ptr< const NavMsg > message)=0
Handle a received message.
Where messages are sent to or received from.
NMEA0183 drivers common base.