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, see <https://www.gnu.org/licenses/>. *
17 **************************************************************************/
18
25#include <mutex> // std::mutex
26#include <queue> // std::queue
27#include <vector>
28
29// For compilers that support precompilation, includes "wx.h".
30#include <wx/wxprec.h>
31
32#ifndef WX_PRECOMP
33#include <wx/wx.h>
34#endif
35
36#include <wx/log.h>
37#include <wx/string.h>
38
39#include "model/comm_buffers.h"
42#include "model/logger.h"
43
44#include "observable.h"
45
46using namespace std::literals::chrono_literals;
47
48CommDriverN0183Serial::CommDriverN0183Serial(const ConnectionParams* params,
49 DriverListener& listener)
50 : CommDriverN0183(NavAddr::Bus::N0183, params->GetStrippedDSPort()),
51 m_portstring(params->GetDSPort()),
52 m_baudrate(params->Baudrate),
53 m_serial_io(SerialIo::Create(
54 [&](const std::vector<unsigned char>& v) { SendMessage(v); },
55 m_portstring, m_baudrate)),
56 m_params(*params),
57 m_listener(listener),
58 m_stats_timer(*this, 2s) {
59 m_garmin_handler = nullptr;
60 this->attributes["commPort"] = params->Port.ToStdString();
61 this->attributes["userComment"] = params->UserComment.ToStdString();
62 this->attributes["ioDirection"] = DsPortTypeToString(params->IOSelect);
63
64 Open();
65}
66
67CommDriverN0183Serial::~CommDriverN0183Serial() { Close(); }
68
69bool CommDriverN0183Serial::Open() {
70 wxString comx;
71 comx = m_params.GetDSPort().AfterFirst(':'); // strip "Serial:"
72 if (comx.IsEmpty()) return false;
73
74 wxString port_uc = m_params.GetDSPort().Upper();
75
76 auto send_func = [&](const std::vector<unsigned char>& v) { SendMessage(v); };
77 if ((wxNOT_FOUND != port_uc.Find("USB")) &&
78 (wxNOT_FOUND != port_uc.Find("GARMIN"))) {
79 m_garmin_handler = new GarminProtocolHandler(comx, send_func, true);
80 } else if (m_params.Garmin) {
81 m_garmin_handler = new GarminProtocolHandler(comx, send_func, false);
82 } else {
83 // Kick off the RX thread
84 m_serial_io->Start();
85 }
86
87 return true;
88}
89
90void CommDriverN0183Serial::Close() {
91 wxLogMessage(
92 wxString::Format("Closing NMEA Driver %s", m_portstring.c_str()));
93
94 m_stats_timer.Stop();
95
96 // Kill off the secondary RX IO if alive
97 if (m_serial_io->IsRunning()) {
98 wxLogMessage("Stopping Secondary Thread");
99 m_serial_io->RequestStop();
100 std::chrono::milliseconds elapsed;
101 if (m_serial_io->WaitUntilStopped(10s, elapsed)) {
102 MESSAGE_LOG << "Stopped in " << elapsed.count() << " msec.";
103 } else {
104 MESSAGE_LOG << "Not stopped after 10 sec.";
105 }
106 }
107
108 // Kill off the Garmin handler, if alive
109 if (m_garmin_handler) {
110 m_garmin_handler->Close();
111 delete m_garmin_handler;
112 m_garmin_handler = nullptr;
113 }
114}
115
116bool CommDriverN0183Serial::IsGarminThreadActive() const {
117 if (m_garmin_handler) {
118 // TODO expand for serial
119#ifdef __WXMSW__
120 if (m_garmin_handler->m_usb_handle != INVALID_HANDLE_VALUE)
121 return true;
122 else
123 return false;
124#endif
125 }
126
127 return false;
128}
129
130void CommDriverN0183Serial::StopGarminUSBIOThread(bool b_pause) const {
131 if (m_garmin_handler) {
132 m_garmin_handler->StopIOThread(b_pause);
133 }
134}
135
136bool CommDriverN0183Serial::SendMessage(std::shared_ptr<const NavMsg> msg,
137 std::shared_ptr<const NavAddr> addr) {
138 auto msg_0183 = std::dynamic_pointer_cast<const Nmea0183Msg>(msg);
139 wxString sentence(msg_0183->payload.c_str());
140
141 if (m_serial_io->IsRunning()) {
142 for (int retries = 0; retries < 10; retries += 1) {
143 if (m_serial_io->SetOutMsg(sentence)) {
144 return true;
145 }
146 }
147 return false; // could not send after several tries....
148 } else {
149 return false;
150 }
151}
152
153void CommDriverN0183Serial::SendMessage(const std::vector<unsigned char>& msg) {
154 // Is this an output-only port?
155 // Commonly used for "Send to GPS" function
156 if (m_params.IOSelect == DS_TYPE_OUTPUT) return;
157
158 SendToListener({msg.begin(), msg.end()}, m_listener, m_params);
159}
NMEA0183 basic parsing common parts:
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
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.
Communication statistics infrastructure.
std::string DsPortTypeToString(dsPortType type)
Return textual representation for use in driver ioDirection attribute.
Enhanced logging interface on top of wx/log.h.
General observable implementation with several specializations.