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