26#include <wx/msw/winundef.h>
33#if defined(HAVE_READLINK) && !defined(HAVE_LIBGEN_H)
34#error Using readlink(3) requires libgen.h which cannot be found.
56 explicit RawKey(
const std::string &key) : m_key(key) {}
57 [[nodiscard]] std::string
GetKey()
const override {
return m_key; }
63static std::string N2K_LogMessage_Detail(
unsigned int pgn) {
64 std::string not_used =
"Not used by OCPN, maybe by Plugins";
68 return "GNSS Position & DBoard: SAT System";
70 return "Position rapid";
72 return "COG/SOG rapid";
74 return "AIS Class A position report";
76 return "AIS Class B position report";
78 return "AIS Aids to Navigation (AtoN) Report";
80 return "AIS Base Station report";
82 return "AIS static data class A";
85 return "AIS static data class B part A";
87 return "AIS static data class B part B";
89 return "Heading rapid";
91 return "GNSS Sats & DBoard: SAT Status";
94 return "DBoard: Rudder data";
96 return "DBoard: Roll Pitch";
98 return "DBoard: Speed through water";
101 return "DBoard: Depth Data";
103 return "DBoard: Distance log";
105 return "DBoard: Wind data";
107 return "DBoard: Environment data";
110 return "System time. " + not_used;
112 return "Man Overboard Notification. " + not_used;
114 return "Heading/Track control. " + not_used;
116 return "Rate of turn. " + not_used;
118 return "Magnetic variation. " + not_used;
120 return "Engine rapid param. " + not_used;
122 return "Engine parameters dynamic. " + not_used;
124 return "Transmission parameters dynamic. " + not_used;
126 return "Trip Parameters, Engine. " + not_used;
128 return "Binary status report. " + not_used;
130 return "Fluid level. " + not_used;
132 return "DC Detailed Status. " + not_used;
134 return "Charger Status. " + not_used;
136 return "Battery Status. " + not_used;
138 return "Battery Configuration Status. " + not_used;
140 return "Leeway. " + not_used;
142 return "Windlass Control Status. " + not_used;
144 return "Windlass Operating Status. " + not_used;
146 return "Windlass Monitoring Status. " + not_used;
148 return "Date,Time & Local offset. " + not_used;
150 return "GNSS DOP data. " + not_used;
152 return "Cross Track Error. " + not_used;
154 return "Navigation info. " + not_used;
156 return "Waypoint list. " + not_used;
158 return "AIS Safety Related Broadcast Message. " + not_used;
160 return "Waypoint list. " + not_used;
162 return "Environmental parameters. " + not_used;
164 return "Temperature. " + not_used;
166 return "Humidity. " + not_used;
168 return "Actual Pressure. " + not_used;
170 return "Set Pressure. " + not_used;
172 return "Temperature extended range. " + not_used;
174 return "Meteorological Station Data. " + not_used;
176 return "Trim Tab Position. " + not_used;
178 return "Direction Data. " + not_used;
180 return "No description. Not used by OCPN, maybe passed to plugins";
184Multiplexer::Multiplexer(
const MuxLogCallbacks &cb,
bool &filter_behaviour)
186 : m_log_callbacks(cb),
187 m_legacy_input_filter_behaviour(filter_behaviour),
188 m_new_msgtype_lstnr(
NavMsgBus::GetInstance().new_msg_event,
190 m_n2k_repeat_count(0),
191 m_last_pgn_logged(0) {
192 if (g_GPS_Ident.IsEmpty()) g_GPS_Ident =
"Generic";
195Multiplexer::~Multiplexer() =
default;
197void Multiplexer::LogOutputMessage(
const std::shared_ptr<const NavMsg> &msg,
199 if (m_log_callbacks.log_is_active()) {
200 ns.direction = NavmsgStatus::Direction::kOutput;
202 m_log_callbacks.log_message(ll);
207 bool is_filtered,
bool is_error,
208 const wxString &error_msg)
const {
209 if (m_log_callbacks.log_is_active()) {
211 ns.direction = NavmsgStatus::Direction::kHandled;
213 ns.status = NavmsgStatus::State::kChecksumError;
216 if (m_legacy_input_filter_behaviour) {
217 ns.accepted = NavmsgStatus::Accepted::kFilteredNoOutput;
219 ns.accepted = NavmsgStatus::Accepted::kFilteredDropped;
222 ns.accepted = NavmsgStatus::Accepted::kOk;
226 ll.error_msg = error_msg;
227 m_log_callbacks.log_message(ll);
231void Multiplexer::HandleN0183(
232 const std::shared_ptr<const Nmea0183Msg> &n0183_msg)
const {
234 const auto &drivers = CommDriverRegistry::GetInstance().
GetDrivers();
235 auto &source_driver =
FindDriver(drivers, n0183_msg->source->iface);
236 if (!source_driver) {
238 if ((n0183_msg->source->iface !=
"virtual")) {
243 std::string error_msg;
244 if (n0183_msg->state == NavMsg::State::kCannotParse)
245 error_msg = _(
"Unparsable NMEA0183 message").ToStdString();
246 else if (n0183_msg->state == NavMsg::State::kBadChecksum)
247 error_msg = _(
"NMEA0183 checksum error").ToStdString();
248 bool is_filtered = n0183_msg->state == NavMsg::State::kFiltered;
249 bool cs_error = n0183_msg->state == NavMsg::State::kBadChecksum;
254 std::string source_iface;
256 source_iface = source_driver->iface;
259 for (
auto &driver : drivers) {
260 if (!driver)
continue;
261 if (driver->bus == NavAddr::Bus::N0183) {
265 bool passes_input_filter = n0183_msg->state != NavMsg::State::kFiltered;
268 std::shared_ptr<const Nmea0183Msg> msg = n0183_msg;
269 if ((m_legacy_input_filter_behaviour && !passes_input_filter) ||
270 passes_input_filter) {
275 if ((!params_.DisableEcho && params_.Type == SERIAL) ||
276 driver->iface != source_iface) {
277 if (params_.IOSelect == DS_TYPE_INPUT_OUTPUT ||
278 params_.IOSelect == DS_TYPE_OUTPUT) {
279 bool bout_filter =
true;
280 bool bxmit_ok =
true;
281 std::string id(
"XXXXX");
282 size_t comma_pos = n0183_msg->payload.find(
',');
283 if (comma_pos != std::string::npos && comma_pos > 5)
284 id = n0183_msg->payload.substr(1, comma_pos - 1);
285 if (params_.SentencePassesFilter(n0183_msg->payload.c_str(),
288 auto null_addr = std::make_shared<NavAddr>();
289 msg = std::make_shared<Nmea0183Msg>(
id, n0183_msg->payload,
291 bxmit_ok = driver->SendMessage(msg, null_addr);
296 if (m_log_callbacks.log_is_active()) {
298 ns.direction = NavmsgStatus::Direction::kOutput;
300 ns.accepted = NavmsgStatus::Accepted::kFilteredDropped;
302 if (!bxmit_ok) ns.status = NavmsgStatus::State::kTxError;
304 auto logaddr = std::make_shared<NavAddr0183>(driver->iface);
305 auto logmsg = std::make_shared<Nmea0183Msg>(
306 id, n0183_msg->payload, logaddr);
307 LogOutputMessage(logmsg, ns);
316bool Multiplexer::HandleN2kLog(
317 const std::shared_ptr<const Nmea2000Msg> &n2k_msg) {
318 if (!m_log_callbacks.log_is_active())
return false;
320 auto payload = n2k_msg->payload;
322 unsigned int pgn = 0;
323 pgn += n2k_msg->payload.at(3);
324 pgn += n2k_msg->payload.at(4) << 8;
325 pgn += n2k_msg->payload.at(5) << 16;
328 if (payload.at(0) == 0x94) {
330 ns.direction = NavmsgStatus::Direction::kOutput;
331 LogOutputMessage(n2k_msg, ns);
334 std::string source = n2k_msg->source->to_string();
337 unsigned char source_id = n2k_msg->payload.at(7);
339 sprintf(ss,
"%d", source_id);
340 std::string ident = std::string(ss);
342 if (pgn == m_last_pgn_logged) {
343 m_n2k_repeat_count++;
346 if (m_n2k_repeat_count) {
347 wxString repeat_log_msg;
348 repeat_log_msg.Printf(
"...Repeated %d times\n", m_n2k_repeat_count);
350 m_n2k_repeat_count = 0;
354 log_msg.Printf(
"PGN: %d Source: %s ID: %s Desc: %s\n", pgn, source, ident,
355 N2K_LogMessage_Detail(pgn).c_str());
359 m_last_pgn_logged = pgn;
364void Multiplexer::OnNewMessageType() {
365 for (
auto msg_key :
NavMsgBus::GetInstance().GetActiveMessages()) {
366 if (m_listeners.find(msg_key) != m_listeners.end())
continue;
369 case NavAddr::Bus::N0183:
370 m_listeners[msg_key] =
372 HandleN0183(UnpackEvtPointer<Nmea0183Msg>(ev));
376 case NavAddr::Bus::N2000:
377 m_listeners[msg_key] =
379 HandleN2kLog(UnpackEvtPointer<Nmea2000Msg>(ev));
NMEA0183 basic parsing common parts:
const std::vector< DriverPtr > & GetDrivers() const
Interface implemented by classes which listens.
Handle logging and forwarding of incoming n0183/n2k messages.
void LogInputMessage(const std::shared_ptr< const NavMsg > &msg, bool is_filtered, bool is_error, const wxString &error_msg="") const
Logs an input message with context information.
The raw message layer, a singleton.
static NavAddr::Bus GetBusByKey(const std::string &key)
Return bus corresponding to given key.
Representation of message status as determined by the multiplexer.
Define an action to be performed when a KeyProvider is notified.
Custom event class for OpenCPN's notification system.
KeyProvider wrapper for a plain key string.
std::string GetKey() const override
Get the Key object from the Key Provider.
DriverPtr & FindDriver(const std::vector< DriverPtr > &drivers, const std::string &iface, const NavAddr::Bus _bus)
Search list of drivers for a driver with given interface string.
Driver registration container, a singleton.
Raw messages layer, supports sending and recieving navmsg messages.
Global variables stored in configuration file.
Multiplexer class and helpers.
std::vector< std::string > split(const char *token_string, const std::string &delimiter)
Return vector of items in s separated by delimiter.
Basic DataMonitor logging interface: LogLine (reflects a line in the log) and NmeaLog,...