OpenCPN Partial API docs
conn_params.cpp
1 /***************************************************************************
2  *
3  * Project: OpenCPN
4  *
5  ***************************************************************************
6  * Copyright (C) 2013 by David S. Register *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the *
20  * Free Software Foundation, Inc., *
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
22  **************************************************************************/
23 
24 // For compilers that support precompilation, includes "wx.h".
25 #include <wx/wxprec.h>
26 
27 #ifndef WX_PRECOMP
28 #include <wx/wx.h>
29 #endif // precompiled headers
30 
31 #ifdef __MINGW32__
32 #undef IPV6STRICT // mingw FTBFS fix: missing struct ip_mreq
33 #include <windows.h>
34 #endif
35 
36 #include <wx/checklst.h>
37 #include <wx/combobox.h>
38 #include <wx/intl.h>
39 #include <wx/regex.h>
40 #include <wx/statline.h>
41 #include <wx/tokenzr.h>
42 
43 #include "model/conn_params.h"
44 
45 #include "ocpn_plugin.h"
46 
47 #if !wxUSE_XLOCALE && wxCHECK_VERSION(3, 0, 0)
48 #define wxAtoi(arg) atoi(arg)
49 #endif
50 
51 static wxArrayOfConnPrm* the_connection_params = 0;
52 
53 wxArrayOfConnPrm* TheConnectionParams() {
54  if (the_connection_params == 0)
55  the_connection_params = new wxArrayOfConnPrm();
56  return the_connection_params;
57 }
58 
59 ConnectionParams::ConnectionParams(const wxString &configStr) {
60  m_optionsPanel = NULL;
61  Deserialize(configStr);
62 }
63 
64 void ConnectionParams::Deserialize(const wxString &configStr) {
65  Valid = true;
66  wxArrayString prms = wxStringTokenize(configStr, _T(";"));
67  if (prms.Count() < 18) {
68  Valid = false;
69  return;
70  }
71 
72  Type = (ConnectionType)wxAtoi(prms[0]);
73  NetProtocol = (NetworkProtocol)wxAtoi(prms[1]);
74  NetworkAddress = prms[2];
75  NetworkPort = (ConnectionType)wxAtoi(prms[3]);
76  Protocol = (DataProtocol)wxAtoi(prms[4]);
77  Port = prms[5];
78  Baudrate = wxAtoi(prms[6]);
79  ChecksumCheck = wxAtoi(prms[7]);
80  int iotval = wxAtoi(prms[8]);
81  IOSelect = ((iotval <= 2) ? static_cast<dsPortType>(iotval) : DS_TYPE_INPUT);
82  InputSentenceListType = (ListType)wxAtoi(prms[9]);
83  InputSentenceList = wxStringTokenize(prms[10], _T(","));
84  OutputSentenceListType = (ListType)wxAtoi(prms[11]);
85  OutputSentenceList = wxStringTokenize(prms[12], _T(","));
86  Priority = wxAtoi(prms[13]);
87  Garmin = !!wxAtoi(prms[14]);
88  GarminUpload = !!wxAtoi(prms[15]);
89  FurunoGP3X = !!wxAtoi(prms[16]);
90 
91  bEnabled = true;
92  LastNetworkPort = 0;
93  b_IsSetup = false;
94  if (prms.Count() >= 18) {
95  bEnabled = !!wxAtoi(prms[17]);
96  }
97  if (prms.Count() >= 19) {
98  UserComment = prms[18];
99  }
100  if (prms.Count() >= 20) {
101  AutoSKDiscover = !!wxAtoi(prms[19]);
102  }
103  if (prms.Count() >= 21) {
104  socketCAN_port = prms[20];
105  }
106  if (prms.Count() >= 22) {
107  NoDataReconnect = wxAtoi(prms[21]);
108  }
109  if (prms.Count() >= 23) {
110  DisableEcho = wxAtoi(prms[22]);
111  }
112  if (prms.Count() >= 24) {
113  AuthToken = prms[22];
114  }
115 }
116 
117 wxString ConnectionParams::Serialize() const {
118  wxString istcs;
119  for (size_t i = 0; i < InputSentenceList.Count(); i++) {
120  if (i > 0) istcs.Append(_T(","));
121  istcs.Append(InputSentenceList[i]);
122  }
123  wxString ostcs;
124  for (size_t i = 0; i < OutputSentenceList.Count(); i++) {
125  if (i > 0) ostcs.Append(_T(","));
126  ostcs.Append(OutputSentenceList[i]);
127  }
128  wxString ret = wxString::Format(
129  _T("%d;%d;%s;%d;%d;%s;%d;%d;%d;%d;%s;%d;%s;%d;%d;%d;%d;%d;%s;%d;%s;%d;%d;%s"), Type,
130  NetProtocol, NetworkAddress.c_str(), NetworkPort, Protocol, Port.c_str(),
131  Baudrate, ChecksumCheck, IOSelect, InputSentenceListType, istcs.c_str(),
132  OutputSentenceListType, ostcs.c_str(), Priority, Garmin, GarminUpload,
133  FurunoGP3X, bEnabled, UserComment.c_str(), AutoSKDiscover, socketCAN_port.c_str(),
134  NoDataReconnect, DisableEcho, AuthToken.c_str());
135 
136  return ret;
137 }
138 
139 ConnectionParams::ConnectionParams() {
140  Type = UNKNOWN;
141  NetProtocol = TCP;
142  NetworkAddress = wxEmptyString;
143  NetworkPort = 0;
144  Protocol = PROTO_NMEA0183;
145  Port = wxEmptyString;
146  Baudrate = 4800;
147  ChecksumCheck = true;
148  Garmin = false;
149  FurunoGP3X = false;
150  IOSelect = DS_TYPE_INPUT;
151  InputSentenceListType = WHITELIST;
152  OutputSentenceListType = WHITELIST;
153  Priority = 0;
154  Valid = true;
155  bEnabled = true;
156  b_IsSetup = false;
157  m_optionsPanel = NULL;
158  AutoSKDiscover = false;
159  NoDataReconnect = false;
160  DisableEcho = false;
161  AuthToken = wxEmptyString;
162 }
163 
164 ConnectionParams::~ConnectionParams() {
165  // delete m_optionsPanel;
166 }
167 
168 wxString ConnectionParams::GetSourceTypeStr() const {
169  switch (Type) {
170  case SERIAL:
171  return _("Serial");
172  case NETWORK:
173  return _("Network");
174  case INTERNAL_GPS:
175  return _("GPS");
176  case INTERNAL_BT:
177  return _("BT");
178  default:
179  return _T("");
180  }
181 }
182 
183 wxString ConnectionParams::GetAddressStr() const {
184  if (Type == SERIAL)
185  return wxString::Format(_T("%s"), Port.c_str());
186  else if (Type == NETWORK)
187  return wxString::Format(_T("%s:%d"), NetworkAddress.c_str(), NetworkPort);
188  else if (Type == INTERNAL_GPS)
189  return _("Internal");
190  else if (Type == INTERNAL_BT)
191  return NetworkAddress;
192  else
193  return _T("");
194 }
195 
196 // TODO: Make part of NetworkProtocol interface
197 static wxString NetworkProtocolToString(NetworkProtocol NetProtocol) {
198  switch (NetProtocol) {
199  case TCP:
200  return _("TCP");
201  case UDP:
202  return _("UDP");
203  case GPSD:
204  return _("GPSD");
205  case SIGNALK:
206  return _("Signal K");
207  default:
208  return _("Undefined");
209  }
210 }
211 
212 wxString ConnectionParams::GetParametersStr() const {
213  switch (Type) {
214  case SERIAL:
215  return wxString::Format(_T("%d"), Baudrate);
216  case NETWORK:
217  return NetworkProtocolToString(NetProtocol);
218  case INTERNAL_GPS:
219  return _T("GPS");
220  case INTERNAL_BT:
221  return Port;
222  default:
223  return _T("");
224  }
225 }
226 
227 wxString ConnectionParams::GetIOTypeValueStr() const {
228  if (IOSelect == DS_TYPE_INPUT)
229  return _("Input");
230  else if (IOSelect == DS_TYPE_OUTPUT)
231  return _("Output");
232  else
233  return _("In/Out");
234 }
235 
236 wxString ConnectionParams::FilterTypeToStr(ListType type,
237  FilterDirection dir) const {
238  if (dir == FILTER_INPUT) {
239  if (type == BLACKLIST)
240  return _("Reject");
241  else
242  return _("Accept");
243  } else {
244  if (type == BLACKLIST)
245  return _("Drop");
246  else
247  return _("Send");
248  }
249 }
250 
251 wxString ConnectionParams::GetFiltersStr() const {
252  wxString istcs;
253  for (size_t i = 0; i < InputSentenceList.Count(); i++) {
254  if (i > 0) istcs.Append(_T(","));
255  istcs.Append(InputSentenceList[i]);
256  }
257  wxString ostcs;
258  for (size_t i = 0; i < OutputSentenceList.Count(); i++) {
259  if (i > 0) ostcs.Append(_T(","));
260  ostcs.Append(OutputSentenceList[i]);
261  }
262  wxString ret = wxEmptyString;
263  if (istcs.Len() > 0) {
264  ret.Append(_("In"));
265  ret.Append(wxString::Format(
266  _T(": %s %s"),
267  FilterTypeToStr(InputSentenceListType, FILTER_INPUT).c_str(),
268  istcs.c_str()));
269  } else
270  ret.Append(_("In: None"));
271 
272  if (ostcs.Len() > 0) {
273  ret.Append(_T(", "));
274  ret.Append(_("Out"));
275  ret.Append(wxString::Format(
276  _T(": %s %s"),
277  FilterTypeToStr(OutputSentenceListType, FILTER_OUTPUT).c_str(),
278  ostcs.c_str()));
279  } else
280  ret.Append(_(", Out: None"));
281  return ret;
282 }
283 
284 wxString ConnectionParams::GetDSPort() const {
285  if (Type == SERIAL)
286  return wxString::Format(_T("Serial:%s"), Port.c_str());
287  else if (Type == NETWORK) {
288  wxString proto = NetworkProtocolToString(NetProtocol);
289  return wxString::Format(_T("%s:%s:%d"), proto.c_str(),
290  NetworkAddress.c_str(), NetworkPort);
291  } else if (Type == INTERNAL_BT) {
292  return Port; // mac
293  } else
294  return _T("");
295 }
296 
297 std::string ConnectionParams::GetStrippedDSPort() {
298  if (Type == SERIAL){
299  wxString t = wxString::Format(_T("Serial:%s"), Port.c_str());
300  wxString comx = t.AfterFirst(':').BeforeFirst(' ');
301  return comx.ToStdString();
302  }
303  else if (Type == NETWORK) {
304  wxString proto = NetworkProtocolToString(NetProtocol);
305  wxString t = wxString::Format(_T("%s:%s:%d"), proto.c_str(),
306  NetworkAddress.c_str(), NetworkPort);
307  return t.ToStdString();
308 
309  } else if (Type == SOCKETCAN) {
310  std::string rv = "socketCAN-";
311  rv += socketCAN_port.ToStdString();
312  return rv;
313  } else if (Type == INTERNAL_BT) {
314  return Port.ToStdString();
315  } else
316  return "";
317 }
318 
319 std::string ConnectionParams::GetLastDSPort() const {
320  if (Type == SERIAL){
321  wxString sp = wxString::Format(_T("Serial:%s"), Port.c_str());
322  return sp.ToStdString();
323  }
324  else {
325  wxString proto = NetworkProtocolToString(LastNetProtocol);
326  wxString sp = wxString::Format(_T("%s:%s:%d"), proto.c_str(),
327  LastNetworkAddress.c_str(), LastNetworkPort);
328  return sp.ToStdString();
329  }
330 }
331 
332 bool ConnectionParams::SentencePassesFilter(const wxString& sentence, FilterDirection direction)
333 {
334  wxArrayString filter;
335  bool listype = false;
336 
337  if (direction == FILTER_INPUT)
338  {
339  filter = InputSentenceList;
340  if (InputSentenceListType == WHITELIST)
341  listype = true;
342  }
343  else
344  {
345  filter = OutputSentenceList;
346  if (OutputSentenceListType == WHITELIST)
347  listype = true;
348  }
349  if (filter.Count() == 0) //Empty list means everything passes
350  return true;
351 
352  wxString fs;
353  for (size_t i = 0; i < filter.Count(); i++)
354  {
355  fs = filter[i];
356  switch (fs.Length())
357  {
358  case 2:
359  if (fs == sentence.Mid(1, 2))
360  return listype;
361  break;
362  case 3:
363  if (fs == sentence.Mid(3, 3))
364  return listype;
365  break;
366  case 5:
367  if (fs == sentence.Mid(1, 5))
368  return listype;
369  break;
370  default:
371  // TODO: regex patterns like ".GPZ.." or 6-character patterns
372  // are rejected in the connection settings dialogue currently
373  // experts simply edit .opencpn/opncpn.config
374  wxRegEx re(fs);
375  if (re.Matches(sentence.Mid(0, 8)))
376  {
377  return listype;
378  }
379  break;
380  }
381  }
382  return !listype;
383 }
384 
385 NavAddr::Bus ConnectionParams::GetCommProtocol(){
386  if (Type == NETWORK){
387  if (NetProtocol == SIGNALK)
388  return NavAddr::Bus::Signalk;
389  else if (NetProtocol == GPSD)
390  return NavAddr::Bus::N0183;
391  }
392 
393  switch (Protocol){
394  case PROTO_NMEA0183:
395  return NavAddr::Bus::N0183;
396  case PROTO_NMEA2000:
397  return NavAddr::Bus::N2000;
398  default:
399  return NavAddr::Bus::Undef;
400  }
401 }
402 
403 NavAddr::Bus ConnectionParams::GetLastCommProtocol(){
404  if (Type == NETWORK){
405  if (LastNetProtocol == SIGNALK)
406  return NavAddr::Bus::Signalk;
407  else if (LastNetProtocol == GPSD)
408  return NavAddr::Bus::N0183;
409  }
410 
411  switch (LastDataProtocol){
412  case PROTO_NMEA0183:
413  return NavAddr::Bus::N0183;
414  case PROTO_NMEA2000:
415  return NavAddr::Bus::N2000;
416  default:
417  return NavAddr::Bus::Undef;
418  }
419 }