OpenCPN Partial API docs
Loading...
Searching...
No Matches
comm_drv_n0183_android_int.cpp
1/***************************************************************************
2 *
3 * Project: OpenCPN
4 * Purpose: Implement comm_drv_n0183_android_int.h -- Nmea 0183 driver.
5 * Author: David Register, Alec Leamas
6 *
7 ***************************************************************************
8 * Copyright (C) 2023 by David Register, Alec Leamas *
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
24 **************************************************************************/
25
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 // precompiled headers
32
33#include <mutex>
34#include <queue>
35#include <vector>
36
37#include <wx/event.h>
38#include <wx/log.h>
39#include <wx/string.h>
40#include <wx/utils.h>
41
42#include "config.h"
43#include "model/comm_drv_n0183_android_int.h"
46
47#ifdef __ANDROID__
48#include "androidUTIL.h"
49#endif
50
51typedef enum DS_ENUM_BUFFER_STATE {
52 DS_RX_BUFFER_EMPTY,
53 DS_RX_BUFFER_FULL
54} _DS_ENUM_BUFFER_STATE;
55
56using namespace std::literals::chrono_literals;
57
58class CommDriverN0183AndroidInt; // fwd
59
60#define MAX_OUT_QUEUE_MESSAGE_LENGTH 100
61
62template <typename T>
64public:
65 size_t size() {
66 std::lock_guard<std::mutex> lock(m_mutex);
67 return m_queque.size();
68 }
69
70 bool empty() {
71 std::lock_guard<std::mutex> lock(m_mutex);
72 return m_queque.empty();
73 }
74
75 const T& front() {
76 std::lock_guard<std::mutex> lock(m_mutex);
77 return m_queque.front();
78 }
79
80 void push(const T& value) {
81 std::lock_guard<std::mutex> lock(m_mutex);
82 m_queque.push(value);
83 }
84
85 void pop() {
86 std::lock_guard<std::mutex> lock(m_mutex);
87 m_queque.pop();
88 }
89
90private:
91 std::queue<T> m_queque;
92 mutable std::mutex m_mutex;
93};
94
95#define OUT_QUEUE_LENGTH 20
96#define MAX_OUT_QUEUE_MESSAGE_LENGTH 100
97
98wxDEFINE_EVENT(wxEVT_COMMDRIVER_N0183_ANDROID_INT,
100
101CommDriverN0183AndroidIntEvent::CommDriverN0183AndroidIntEvent(
102 wxEventType commandType, int id = 0)
103 : wxEvent(id, commandType) {};
104
105CommDriverN0183AndroidIntEvent::~CommDriverN0183AndroidIntEvent() {};
106
107void CommDriverN0183AndroidIntEvent::SetPayload(
108 std::shared_ptr<std::vector<unsigned char>> data) {
109 m_payload = data;
110}
111std::shared_ptr<std::vector<unsigned char>>
112CommDriverN0183AndroidIntEvent::GetPayload() {
113 return m_payload;
114}
115
116// required for sending with wxPostEvent()
117wxEvent* CommDriverN0183AndroidIntEvent::Clone() const {
120 newevent->m_payload = this->m_payload;
121 return newevent;
122};
123
124template <class T>
125class circular_buffer {
126public:
127 explicit circular_buffer(size_t size)
128 : buf_(std::unique_ptr<T[]>(new T[size])), max_size_(size) {}
129
130 void reset();
131 size_t capacity() const;
132 size_t size() const;
133
134 bool empty() const {
135 // if head and tail are equal, we are empty
136 return (!full_ && (head_ == tail_));
137 }
138
139 bool full() const {
140 // If tail is ahead the head by 1, we are full
141 return full_;
142 }
143
144 void put(T item) {
145 std::lock_guard<std::mutex> lock(mutex_);
146 buf_[head_] = item;
147 if (full_) tail_ = (tail_ + 1) % max_size_;
148
149 head_ = (head_ + 1) % max_size_;
150
151 full_ = head_ == tail_;
152 }
153
154 T get() {
155 std::lock_guard<std::mutex> lock(mutex_);
156
157 if (empty()) return T();
158
159 // Read data and advance the tail (we now have a free space)
160 auto val = buf_[tail_];
161 full_ = false;
162 tail_ = (tail_ + 1) % max_size_;
163
164 return val;
165 }
166
167private:
168 std::mutex mutex_;
169 std::unique_ptr<T[]> buf_;
170 size_t head_ = 0;
171 size_t tail_ = 0;
172 const size_t max_size_;
173 bool full_ = 0;
174};
175
176CommDriverN0183AndroidInt::CommDriverN0183AndroidInt(
177 const ConnectionParams* params, DriverListener& listener)
178 : CommDriverN0183(NavAddr::Bus::N0183, params->GetStrippedDSPort()),
179 m_bok(false),
180 m_portstring(params->GetDSPort()),
181 m_stats_timer(*this, 2s),
182 m_params(*params),
183 m_listener(listener) {
184 this->attributes["commPort"] = params->Port.ToStdString();
185 this->attributes["userComment"] = params->UserComment.ToStdString();
186 this->attributes["ioDirection"] = DsPortTypeToString(params->IOSelect);
187 m_driver_stats.driver_bus = NavAddr::Bus::N0183;
188 m_driver_stats.driver_iface = params->GetStrippedDSPort();
189
190 // Prepare the wxEventHandler to accept events from the actual hardware thread
191 Bind(wxEVT_COMMDRIVER_N0183_ANDROID_INT,
192 &CommDriverN0183AndroidInt::handle_N0183_MSG, this);
193
194 Open();
195}
196
197CommDriverN0183AndroidInt::~CommDriverN0183AndroidInt() { Close(); }
198
199bool CommDriverN0183AndroidInt::Open() {
200 androidStartGPS(this);
201 m_driver_stats.available = true;
202 return true;
203}
204
205void CommDriverN0183AndroidInt::Close() {
206 wxLogMessage(
207 wxString::Format(_T("Closing NMEA Driver %s"), m_portstring.c_str()));
208
209 androidStopGPS();
210 m_driver_stats.available = false;
211
212 Unbind(wxEVT_COMMDRIVER_N0183_ANDROID_INT,
213 &CommDriverN0183AndroidInt::handle_N0183_MSG, this);
214}
215
216bool CommDriverN0183AndroidInt::SendMessage(
217 std::shared_ptr<const NavMsg> msg, std::shared_ptr<const NavAddr> addr) {
218 return false;
219}
220
221void CommDriverN0183AndroidInt::handle_N0183_MSG(
223 auto p = event.GetPayload();
224 std::vector<unsigned char>* payload = p.get();
225
226 m_driver_stats.rx_count += payload->size();
227
228 // Extract the NMEA0183 sentence
229 std::string full_sentence = std::string(payload->begin(), payload->end());
230
231 if ((full_sentence[0] == '$') || (full_sentence[0] == '!')) { // Sanity check
232 std::string identifier;
233 // We notify based on full message, including the Talker ID
234 identifier = full_sentence.substr(1, 5);
235
236 // notify message listener and also "ALL" N0183 messages, to support plugin
237 // API using original talker id
238 auto msg = std::make_shared<const Nmea0183Msg>(identifier, full_sentence,
239 GetAddress());
240 auto msg_all = std::make_shared<const Nmea0183Msg>(*msg, "ALL");
241
242 if (m_params.SentencePassesFilter(full_sentence, FILTER_INPUT))
243 m_listener.Notify(std::move(msg));
244
245 m_listener.Notify(std::move(msg_all));
246 }
247}
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.
Driver registration container, a singleton.
Raw messages layer, supports sending and recieving navmsg messages.
unsigned rx_count
Number of bytes received since program start.