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
56class CommDriverN0183AndroidInt; // fwd
57
58#define MAX_OUT_QUEUE_MESSAGE_LENGTH 100
59
60template <typename T>
62public:
63 size_t size() {
64 std::lock_guard<std::mutex> lock(m_mutex);
65 return m_queque.size();
66 }
67
68 bool empty() {
69 std::lock_guard<std::mutex> lock(m_mutex);
70 return m_queque.empty();
71 }
72
73 const T& front() {
74 std::lock_guard<std::mutex> lock(m_mutex);
75 return m_queque.front();
76 }
77
78 void push(const T& value) {
79 std::lock_guard<std::mutex> lock(m_mutex);
80 m_queque.push(value);
81 }
82
83 void pop() {
84 std::lock_guard<std::mutex> lock(m_mutex);
85 m_queque.pop();
86 }
87
88private:
89 std::queue<T> m_queque;
90 mutable std::mutex m_mutex;
91};
92
93#define OUT_QUEUE_LENGTH 20
94#define MAX_OUT_QUEUE_MESSAGE_LENGTH 100
95
96wxDEFINE_EVENT(wxEVT_COMMDRIVER_N0183_ANDROID_INT,
98
99CommDriverN0183AndroidIntEvent::CommDriverN0183AndroidIntEvent(
100 wxEventType commandType, int id = 0)
101 : wxEvent(id, commandType) {};
102
103CommDriverN0183AndroidIntEvent::~CommDriverN0183AndroidIntEvent() {};
104
105void CommDriverN0183AndroidIntEvent::SetPayload(
106 std::shared_ptr<std::vector<unsigned char>> data) {
107 m_payload = data;
108}
109std::shared_ptr<std::vector<unsigned char>>
110CommDriverN0183AndroidIntEvent::GetPayload() {
111 return m_payload;
112}
113
114// required for sending with wxPostEvent()
115wxEvent* CommDriverN0183AndroidIntEvent::Clone() const {
118 newevent->m_payload = this->m_payload;
119 return newevent;
120};
121
122template <class T>
123class circular_buffer {
124public:
125 explicit circular_buffer(size_t size)
126 : buf_(std::unique_ptr<T[]>(new T[size])), max_size_(size) {}
127
128 void reset();
129 size_t capacity() const;
130 size_t size() const;
131
132 bool empty() const {
133 // if head and tail are equal, we are empty
134 return (!full_ && (head_ == tail_));
135 }
136
137 bool full() const {
138 // If tail is ahead the head by 1, we are full
139 return full_;
140 }
141
142 void put(T item) {
143 std::lock_guard<std::mutex> lock(mutex_);
144 buf_[head_] = item;
145 if (full_) tail_ = (tail_ + 1) % max_size_;
146
147 head_ = (head_ + 1) % max_size_;
148
149 full_ = head_ == tail_;
150 }
151
152 T get() {
153 std::lock_guard<std::mutex> lock(mutex_);
154
155 if (empty()) return T();
156
157 // Read data and advance the tail (we now have a free space)
158 auto val = buf_[tail_];
159 full_ = false;
160 tail_ = (tail_ + 1) % max_size_;
161
162 return val;
163 }
164
165private:
166 std::mutex mutex_;
167 std::unique_ptr<T[]> buf_;
168 size_t head_ = 0;
169 size_t tail_ = 0;
170 const size_t max_size_;
171 bool full_ = 0;
172};
173
174CommDriverN0183AndroidInt::CommDriverN0183AndroidInt(
175 const ConnectionParams* params, DriverListener& listener)
176 : CommDriverN0183(NavAddr::Bus::N0183, params->GetStrippedDSPort()),
177 m_bok(false),
178 m_portstring(params->GetDSPort()),
179 m_params(*params),
180 m_listener(listener) {
181 this->attributes["commPort"] = params->Port.ToStdString();
182 this->attributes["userComment"] = params->UserComment.ToStdString();
183 this->attributes["ioDirection"] = DsPortTypeToString(params->IOSelect);
184
185 // Prepare the wxEventHandler to accept events from the actual hardware thread
186 Bind(wxEVT_COMMDRIVER_N0183_ANDROID_INT,
187 &CommDriverN0183AndroidInt::handle_N0183_MSG, this);
188
189 Open();
190}
191
192CommDriverN0183AndroidInt::~CommDriverN0183AndroidInt() { Close(); }
193
194bool CommDriverN0183AndroidInt::Open() {
195 androidStartGPS(this);
196 return true;
197}
198
199void CommDriverN0183AndroidInt::Close() {
200 wxLogMessage(
201 wxString::Format(_T("Closing NMEA Driver %s"), m_portstring.c_str()));
202
203 androidStopGPS();
204
205 Unbind(wxEVT_COMMDRIVER_N0183_ANDROID_INT,
206 &CommDriverN0183AndroidInt::handle_N0183_MSG, this);
207}
208
209bool CommDriverN0183AndroidInt::SendMessage(
210 std::shared_ptr<const NavMsg> msg, std::shared_ptr<const NavAddr> addr) {
211 return false;
212}
213
214void CommDriverN0183AndroidInt::handle_N0183_MSG(
216 auto p = event.GetPayload();
217 std::vector<unsigned char>* payload = p.get();
218
219 // Extract the NMEA0183 sentence
220 std::string full_sentence = std::string(payload->begin(), payload->end());
221
222 if ((full_sentence[0] == '$') || (full_sentence[0] == '!')) { // Sanity check
223 std::string identifier;
224 // We notify based on full message, including the Talker ID
225 identifier = full_sentence.substr(1, 5);
226
227 // notify message listener and also "ALL" N0183 messages, to support plugin
228 // API using original talker id
229 auto msg = std::make_shared<const Nmea0183Msg>(identifier, full_sentence,
230 GetAddress());
231 auto msg_all = std::make_shared<const Nmea0183Msg>(*msg, "ALL");
232
233 if (m_params.SentencePassesFilter(full_sentence, FILTER_INPUT))
234 m_listener.Notify(std::move(msg));
235
236 m_listener.Notify(std::move(msg_all));
237 }
238}
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.