OpenCPN Partial API docs
Loading...
Searching...
No Matches
comm_drv_n0183_serial.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * Copyright (C) 2022 David Register *
3 * Copyright (C) 2022 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, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 **************************************************************************/
20
26// For compilers that support precompilation, includes "wx.h".
27#include <wx/wxprec.h>
28
29#ifndef WX_PRECOMP
30#include <wx/wx.h>
31#endif
32
33#include <mutex> // std::mutex
34#include <queue> // std::queue
35#include <vector>
36
37#include <wx/log.h>
38#include <wx/string.h>
39
40#include "config.h"
41#include "model/comm_buffers.h"
45#include "model/logger.h"
46#include "model/wait_continue.h"
47
48#include "observable.h"
49
50using namespace std::literals::chrono_literals;
51
52CommDriverN0183Serial::CommDriverN0183Serial(const ConnectionParams* params,
53 DriverListener& listener)
54 : CommDriverN0183(NavAddr::Bus::N0183, params->GetStrippedDSPort()),
55 m_portstring(params->GetDSPort()),
56 m_baudrate(params->Baudrate),
57 m_serial_io(SerialIo::Create(
58 [&](const std::vector<unsigned char>& v) { SendMessage(v); },
59 m_portstring, m_baudrate)),
60 m_params(*params),
61 m_listener(listener),
62 m_stats_timer(*this, 2s) {
63 m_garmin_handler = nullptr;
64 this->attributes["commPort"] = params->Port.ToStdString();
65 this->attributes["userComment"] = params->UserComment.ToStdString();
66 this->attributes["ioDirection"] = DsPortTypeToString(params->IOSelect);
67
68 Open();
69}
70
71CommDriverN0183Serial::~CommDriverN0183Serial() { Close(); }
72
73bool CommDriverN0183Serial::Open() {
74 wxString comx;
75 comx = m_params.GetDSPort().AfterFirst(':'); // strip "Serial:"
76 if (comx.IsEmpty()) return false;
77
78 wxString port_uc = m_params.GetDSPort().Upper();
79
80 auto send_func = [&](const std::vector<unsigned char>& v) { SendMessage(v); };
81 if ((wxNOT_FOUND != port_uc.Find("USB")) &&
82 (wxNOT_FOUND != port_uc.Find("GARMIN"))) {
83 m_garmin_handler = new GarminProtocolHandler(comx, send_func, true);
84 } else if (m_params.Garmin) {
85 m_garmin_handler = new GarminProtocolHandler(comx, send_func, false);
86 } else {
87 // strip off any description provided by Windows
88 comx = comx.BeforeFirst(' ');
89
90 // Kick off the RX thread
91 m_serial_io->Start();
92 }
93
94 return true;
95}
96
97void CommDriverN0183Serial::Close() {
98 wxLogMessage(
99 wxString::Format("Closing NMEA Driver %s", m_portstring.c_str()));
100
101 // Kill off the secondary RX IO if alive
102 if (m_serial_io->IsRunning()) {
103 wxLogMessage("Stopping Secondary Thread");
104 m_serial_io->RequestStop();
105 std::chrono::milliseconds elapsed;
106 if (m_serial_io->WaitUntilStopped(10s, elapsed)) {
107 MESSAGE_LOG << "Stopped in " << elapsed.count() << " msec.";
108 } else {
109 MESSAGE_LOG << "Not stopped after 10 sec.";
110 }
111 }
112
113 // Kill off the Garmin handler, if alive
114 if (m_garmin_handler) {
115 m_garmin_handler->Close();
116 delete m_garmin_handler;
117 m_garmin_handler = nullptr;
118 }
119}
120
121bool CommDriverN0183Serial::IsGarminThreadActive() {
122 if (m_garmin_handler) {
123 // TODO expand for serial
124#ifdef __WXMSW__
125 if (m_garmin_handler->m_usb_handle != INVALID_HANDLE_VALUE)
126 return true;
127 else
128 return false;
129#endif
130 }
131
132 return false;
133}
134
135void CommDriverN0183Serial::StopGarminUSBIOThread(bool b_pause) {
136 if (m_garmin_handler) {
137 m_garmin_handler->StopIOThread(b_pause);
138 }
139}
140
141bool CommDriverN0183Serial::SendMessage(std::shared_ptr<const NavMsg> msg,
142 std::shared_ptr<const NavAddr> addr) {
143 auto msg_0183 = std::dynamic_pointer_cast<const Nmea0183Msg>(msg);
144 wxString sentence(msg_0183->payload.c_str());
145
146 if (m_serial_io->IsRunning()) {
147 for (int retries = 0; retries < 10; retries += 1) {
148 if (m_serial_io->SetOutMsg(sentence)) {
149 return true;
150 }
151 }
152 return false; // could not send after several tries....
153 } else {
154 return false;
155 }
156}
157
158void CommDriverN0183Serial::SendMessage(const std::vector<unsigned char>& msg) {
159 // Is this an output-only port?
160 // Commonly used for "Send to GPS" function
161 if (m_params.IOSelect == DS_TYPE_OUTPUT) return;
162
163 // sanity checks
164 if (msg.size() < 6) return;
165 if (msg[0] != '$' && msg[0] != '!') return;
166
167 // We use the full src + type to discriminate messages, like GPGGA
168 std::string identifier(msg.begin() + 1, msg.begin() + 6);
169
170 // notify msg listener and also "ALL" N0183 messages, to support plugin
171 // API using original talker id
172 std::string payload(msg.begin(), msg.end());
173 auto message =
174 std::make_shared<const Nmea0183Msg>(identifier, payload, GetAddress());
175 auto message_all = std::make_shared<const Nmea0183Msg>(*message, "ALL");
176
177 if (m_params.SentencePassesFilter(payload, FILTER_INPUT))
178 m_listener.Notify(std::move(message));
179 m_listener.Notify(std::move(message_all));
180}
NMEA0183 drivers common part.
Interface implemented by transport layer and possible other parties like test code which should handl...
Definition comm_driver.h:48
virtual void Notify(std::shared_ptr< const NavMsg > message)=0
Handle a received message.
Where messages are sent to or received from.
Nmea0183 serial communications wrapper, possibly running a thread.
Definition serial_io.h:54
Line-oriented input/output buffers.
NMEA0183 serial driver.
Driver registration container, a singleton.
Communication statistics infrastructure.
Enhanced logging interface on top of wx/log.h.
Basic synchronization primitive.