OpenCPN Partial API docs
Loading...
Searching...
No Matches
comm_drv_n0183.cpp
Go to the documentation of this file.
1/**************************************************************************
2 * Copyright (C) 2022 David Register *
3 * Copyright (C) 2022 - 2025 Alec Leamas *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, see <https://www.gnu.org/licenses/>. *
17 **************************************************************************/
18
25// For compilers that support precompilation, includes "wx.h".
26#include <wx/wxprec.h>
27#ifndef WX_PRECOMP
28#include <wx/wx.h>
29#endif
30
32
34static bool Is0183ChecksumOk(const std::string& sentence) {
35 const size_t cs_start = sentence.find('*');
36 if (cs_start == std::string::npos || cs_start > sentence.size() - 3)
37 return false; // Not found, or didn't have 2 characters following it.
38
39 const std::string cs_str = sentence.substr(cs_start + 1, 2);
40 const unsigned long checksum = strtol(cs_str.c_str(), nullptr, 16);
41 if (checksum == 0L && cs_str != "00") return false;
42
43 unsigned char calculated_checksum = 0;
44 for (const char c : sentence.substr(1, cs_start - 1))
45 calculated_checksum ^= static_cast<unsigned char>(c);
46 return calculated_checksum == checksum;
47}
48
55static std::string GetPayloadSentence(const std::string& sentence) {
56 size_t start_pos = sentence.find('$');
57 if (start_pos == std::string::npos) start_pos = sentence.find('!');
58 if (start_pos == std::string::npos) return "";
59 if (sentence.size() < start_pos + 6) return "";
60 return sentence.substr(start_pos);
61}
62
63CommDriverN0183::CommDriverN0183() : AbstractCommDriver(NavAddr::Bus::N0183) {}
64
65CommDriverN0183::CommDriverN0183(NavAddr::Bus, const std::string& s)
66 : AbstractCommDriver(NavAddr::Bus::N0183, s) {}
67
68CommDriverN0183::~CommDriverN0183() = default;
69
70void CommDriverN0183::SendToListener(const std::string& payload,
71 DriverListener& listener,
72 const ConnectionParams& params) {
73 const std::string sentence = GetPayloadSentence(payload);
74 if (sentence.empty()) return;
75 assert(sentence[0] == '$' || sentence[0] == '!');
76 assert(sentence.size() >= 6);
77
78 const bool is_garbage =
79 sentence.size() > 128 ||
80 std::any_of(sentence.begin(), sentence.end(),
81 [](char c) { return !isprint(c) && c != '\n' && c != '\r'; });
82 const bool has_checksum =
83 sentence.find('*', sentence.size() - 6) != std::string::npos;
84
85 NavMsg::State state;
86 if (is_garbage)
87 state = NavMsg::State::kCannotParse;
88 else if (!params.SentencePassesFilter(sentence, FILTER_INPUT))
89 state = NavMsg::State::kFiltered;
90 else if (has_checksum && !Is0183ChecksumOk(sentence))
91 state = NavMsg::State::kBadChecksum;
92 else
93 state = NavMsg::State::kOk;
94
95 if (is_garbage) {
96 auto msg = std::make_shared<const Nmea0183Msg>("TRASH", payload,
97 GetAddress(), state);
98 listener.Notify(std::move(msg));
99 } else {
100 // We notify based on full message, including the Talker ID
101 const std::string id = sentence.substr(1, 5);
102 auto msg =
103 std::make_shared<const Nmea0183Msg>(id, sentence, GetAddress(), state);
104 listener.Notify(std::move(msg));
105 }
106}
Common interface for all drivers.
Definition comm_driver.h:65
void SendToListener(const std::string &payload, DriverListener &listener, const ConnectionParams &params)
Wrap argument string in NavMsg pointer, forward to listener.
Interface for handling incoming messages.
Definition comm_driver.h:50
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.