OpenCPN Partial API docs
Loading...
Searching...
No Matches
connection_edit.cpp
1/******************************************************************************
2 *
3 * Project: OpenCPN
4 * Purpose:
5 * Author: David Register
6 *
7 ***************************************************************************
8 * Copyright (C) 2022 by David S. Register *
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 *
27 */
28
29#include <set>
30
31#include <wx/wxprec.h>
32
33#ifndef WX_PRECOMP
34#include <wx/wx.h>
35#endif // precompiled headers
36
37#include "config.h"
38
39#include <wx/tokenzr.h>
40#include <wx/regex.h>
41
42#if defined(__linux__) && !defined(__ANDROID__)
43#include <linux/can.h>
44#include <linux/can/raw.h>
45#include <net/if.h>
46#include <serial/serial.h>
47#include <sys/ioctl.h>
48#include <sys/socket.h>
49#include "dnet.h"
50#endif
51
52#ifdef __ANDROID__
53#include "androidUTIL.h"
54#include "qdebug.h"
55#endif
56
57#include "model/comm_drv_factory.h"
58#include "model/config_vars.h"
59#include "model/ocpn_utils.h"
60#include "model/ser_ports.h"
61#include "model/sys_events.h"
62
63#include "connection_edit.h"
64#include "conn_params_panel.h"
65#include "gui_lib.h"
66#include "nmea0183.h"
67#include "OCPNPlatform.h"
68#include "ocpn_plugin.h" // FIXME for GetOCPNScaledFont_PlugIn
69#include "options.h"
70#include "priority_gui.h"
71#include "udev_rule_mgr.h"
72
73extern OCPNPlatform* g_Platform;
74
75static wxString StringArrayToString(const wxArrayString& arr) {
76 wxString ret = wxEmptyString;
77 for (size_t i = 0; i < arr.Count(); i++) {
78 if (i > 0) ret.Append(",");
79 ret.Append(arr[i]);
80 }
81 return ret;
82}
83
84// Check available SocketCAN interfaces
85
86#if defined(__linux__) && !defined(__ANDROID__)
87static intf_t* intf;
88std::vector<std::string> can_if_candidates;
89static int print_intf(const struct intf_entry* entry, void* arg) {
90 std::string iface = entry->intf_name;
91 if (entry->intf_type == 1 && iface.find("can") != std::string::npos) {
92 can_if_candidates.push_back(entry->intf_name);
93 }
94 return 0;
95}
96#endif
97
98static wxArrayString GetAvailableSocketCANInterfaces() {
99 wxArrayString rv;
100
101#if defined(__linux__) && !defined(__ANDROID__)
102 struct intf_entry* entry;
103
104 can_if_candidates.clear();
105
106 if ((intf = intf_open()) == NULL) {
107 wxLogWarning("Error opening interface list");
108 }
109
110 if (intf_loop(intf, print_intf, NULL) < 0) {
111 wxLogWarning("Error looping over interface list");
112 }
113 intf_close(intf);
114
115 for (const auto& iface : can_if_candidates) {
116 int sock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
117 if (sock < 0) {
118 continue;
119 }
120
121 // Get the interface index
122 struct ifreq if_request;
123 strcpy(if_request.ifr_name, iface.c_str());
124 if (ioctl(sock, SIOCGIFINDEX, &if_request) < 0) {
125 continue;
126 }
127
128 // Check if interface is UP
129 struct sockaddr_can can_address;
130 can_address.can_family = AF_CAN;
131 can_address.can_ifindex = if_request.ifr_ifindex;
132 if (ioctl(sock, SIOCGIFFLAGS, &if_request) < 0) {
133 continue;
134 }
135 if (if_request.ifr_flags & IFF_UP) {
136 rv.Add(iface);
137 } else {
138 continue;
139 }
140 }
141#endif
142 return rv;
143}
144
145static void LoadSerialPorts(wxComboBox* box) {
147 class PortSorter {
148 private:
149 std::string GetKey(const std::string& s) const {
150 if (s.find("->") == std::string::npos) return s;
151 return ocpn::trim(ocpn::split(s, "->")[1]) + " link";
152 }
153
154 public:
155 bool operator()(const std::string& lhs, const std::string& rhs) const {
156 return GetKey(lhs) < GetKey(rhs);
157 }
158 } port_sorter;
159
160 std::set<std::string, PortSorter> sorted_ports(port_sorter);
161 std::unique_ptr<wxArrayString> ports(EnumerateSerialPorts());
162 for (size_t i = 0; i < ports->GetCount(); i++)
163 sorted_ports.insert((*ports)[i].ToStdString());
164
165 box->Clear();
166 for (auto& p : sorted_ports) box->Append(p);
167}
168
169//------------------------------------------------------------------------------
170// ConnectionEditDialog Implementation
171//------------------------------------------------------------------------------
172
173// BEGIN_EVENT_TABLE(ConnectionEditDialog, wxDialog)
174// EVT_TIMER(ID_BT_SCANTIMER, ConnectionEditDialog::onBTScanTimer)
175// END_EVENT_TABLE()
176
177// Define constructors
178ConnectionEditDialog::ConnectionEditDialog() {}
179
180ConnectionEditDialog::ConnectionEditDialog(wxWindow* parent)
181 : wxDialog(parent, wxID_ANY, _("Connection Edit"), wxDefaultPosition,
182 wxSize(560, 840)) {
183 m_parent = parent;
184
185 Init();
186 // Layout();
187 // Fit();
188 // Show();
189}
190
191ConnectionEditDialog::~ConnectionEditDialog() {}
192
193void ConnectionEditDialog::SetInitialSettings(void) {
194 LoadSerialPorts(m_comboPort);
195}
196
197void ConnectionEditDialog::Init() {
198 MORE = "<span foreground=\'blue\'>";
199 MORE += _("More");
200 MORE += "...</span>";
201 LESS = "<span foreground=\'blue\'>";
202 LESS += _("Less");
203 LESS += "...</span>";
204
205 // For small displays, skip the "More" text.
206 // if (g_Platform->getDisplaySize().x < 80 * GetCharWidth()) MORE = "";
207
208 // Setup some inital values
209 m_buttonScanBT = 0;
210 m_stBTPairs = 0;
211 m_choiceBTDataSources = 0;
212
213 m_BTScanTimer.SetOwner(this, ID_BT_SCANTIMER);
214 m_BTscanning = 0;
215 wxSize displaySize = wxGetDisplaySize();
216
217 // Create the UI
218
219 wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
220
221 wxBoxSizer* boxSizer02 = new wxBoxSizer(wxVERTICAL);
222 mainSizer->Add(boxSizer02, 1, wxEXPAND | wxALL, 2);
223
224 m_scrolledwin =
225 new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxSize(-1, -1),
226 wxTAB_TRAVERSAL | wxVSCROLL);
227 m_scrolledwin->SetScrollRate(0, 5);
228 boxSizer02->Add(m_scrolledwin, 1, wxALL | wxEXPAND, 3);
229
230 auto boxSizerSWin = new wxBoxSizer(wxVERTICAL);
231 m_scrolledwin->SetSizer(boxSizerSWin);
232
233 wxStdDialogButtonSizer* btnSizer = new wxStdDialogButtonSizer();
234 wxButton* btnOK = new wxButton(this, wxID_OK);
235 wxButton* btnCancel = new wxButton(this, wxID_CANCEL, _("Cancel"));
236 btnSizer->AddButton(btnOK);
237 btnSizer->AddButton(btnCancel);
238 btnSizer->Realize();
239 mainSizer->Add(btnSizer, 0, wxALL | wxEXPAND, 5);
240
241 SetSizer(mainSizer);
242
243 int group_item_spacing = 2;
244
245 wxFont* dFont = GetOCPNScaledFont_PlugIn(_("Dialog"));
246 double font_size = dFont->GetPointSize() * 17 / 16;
247 wxFont* bFont = wxTheFontList->FindOrCreateFont(
248 font_size, dFont->GetFamily(), dFont->GetStyle(), wxFONTWEIGHT_BOLD);
249 //
250 // m_stEditCon = new wxStaticText(m_pNMEAForm, wxID_ANY, _("Edit Selected
251 // Connection")); m_stEditCon->SetFont(*bFont); bSizer19->Add(m_stEditCon,
252 // 0, wxALL | wxEXPAND | wxALIGN_CENTER_HORIZONTAL, 5);
253 //
254
255 // Connections Properties
256 m_sbConnEdit =
257 new wxStaticBox(m_scrolledwin, wxID_ANY, _("Edit Selected Connection"));
258 m_sbConnEdit->SetFont(*bFont);
259
260 sbSizerConnectionProps = new wxStaticBoxSizer(m_sbConnEdit, wxVERTICAL);
261 m_scrolledwin->GetSizer()->Add(sbSizerConnectionProps, 1, wxALL | wxEXPAND,
262 5);
263
264 wxBoxSizer* bSizer15;
265 bSizer15 = new wxBoxSizer(wxHORIZONTAL);
266
267 sbSizerConnectionProps->Add(bSizer15, 0, wxTOP | wxEXPAND, 5);
268 // bSizer4->Add(bSizerOuterContainer, 1, wxEXPAND, 5);
269
270 m_rbTypeSerial =
271 new wxRadioButton(m_scrolledwin, wxID_ANY, _("Serial"), wxDefaultPosition,
272 wxDefaultSize, wxRB_GROUP);
273 m_rbTypeSerial->SetValue(TRUE);
274 bSizer15->Add(m_rbTypeSerial, 0, wxALL, 5);
275
276 m_rbTypeNet = new wxRadioButton(m_scrolledwin, wxID_ANY, _("Network"),
277 wxDefaultPosition, wxDefaultSize, 0);
278 bSizer15->Add(m_rbTypeNet, 0, wxALL, 5);
279
280 m_rbTypeCAN = new wxRadioButton(m_scrolledwin, wxID_ANY, "socketCAN",
281 wxDefaultPosition, wxDefaultSize, 0);
282#if defined(__linux__) && !defined(__ANDROID__) && !defined(__WXOSX__)
283 bSizer15->Add(m_rbTypeCAN, 0, wxALL, 5);
284#else
285 m_rbTypeCAN->Hide();
286#endif
287
288 wxBoxSizer* bSizer15a = new wxBoxSizer(wxHORIZONTAL);
289 sbSizerConnectionProps->Add(bSizer15a, 0, wxEXPAND, 5);
290
291 if (OCPNPlatform::hasInternalGPS()) {
292 m_rbTypeInternalGPS =
293 new wxRadioButton(m_scrolledwin, wxID_ANY, _("Built-in GPS"),
294 wxDefaultPosition, wxDefaultSize, 0);
295 bSizer15a->Add(m_rbTypeInternalGPS, 0, wxALL, 5);
296 } else
297 m_rbTypeInternalGPS = NULL;
298
299 // has built-in Bluetooth
300 if (OCPNPlatform::hasInternalBT()) {
301 m_rbTypeInternalBT =
302 new wxRadioButton(m_scrolledwin, wxID_ANY, _("Built-in Bluetooth SPP"),
303 wxDefaultPosition, wxDefaultSize, 0);
304 bSizer15a->Add(m_rbTypeInternalBT, 0, wxALL, 5);
305
306 m_buttonScanBT = new wxButton(m_scrolledwin, wxID_ANY, _("BT Scan"),
307 wxDefaultPosition, wxDefaultSize);
308 m_buttonScanBT->Hide();
309
310 // wxBoxSizer* bSizer15a = new wxBoxSizer(wxHORIZONTAL);
311 // sbSizerConnectionProps->Add(bSizer15a, 0, wxEXPAND, 5);
312
313 sbSizerConnectionProps->Add(m_buttonScanBT, 0, wxALL, 5);
314
315 m_stBTPairs =
316 new wxStaticText(m_scrolledwin, wxID_ANY, _("Bluetooth Data Sources"),
317 wxDefaultPosition, wxDefaultSize, 0);
318 m_stBTPairs->Wrap(-1);
319 m_stBTPairs->Hide();
320 sbSizerConnectionProps->Add(m_stBTPairs, 0, wxALL, 5);
321
322 wxArrayString mt;
323 mt.Add("unscanned");
324
325 int ref_size = m_scrolledwin->GetCharWidth();
326 m_choiceBTDataSources =
327 new wxChoice(m_scrolledwin, wxID_ANY, wxDefaultPosition,
328 wxSize(40 * ref_size, 2 * ref_size), mt);
329 // m_choiceBTDataSources->Bind(wxEVT_MOUSEWHEEL,
330 // &ConnectionEditDialog::OnWheelChoice, this);
331 m_choiceBTDataSources->SetSelection(0);
332 m_choiceBTDataSources->Hide();
333 sbSizerConnectionProps->Add(m_choiceBTDataSources, 1, wxEXPAND | wxTOP, 5);
334
335 } else
336 m_rbTypeInternalBT = NULL;
337
338 gSizerNetProps = new wxFlexGridSizer(0, 2, 0, 0);
339
340 sbSizerConnectionProps->Add(gSizerNetProps, 0, wxEXPAND, 5);
341
342 m_stNetProto =
343 new wxStaticText(m_scrolledwin, wxID_ANY, _("Network Protocol"),
344 wxDefaultPosition, wxDefaultSize, 0);
345 m_stNetProto->Wrap(-1);
346 gSizerNetProps->Add(m_stNetProto, 0, wxALL, 5);
347
348 wxBoxSizer* bSizer16;
349 bSizer16 = new wxBoxSizer(wxHORIZONTAL);
350 gSizerNetProps->Add(bSizer16, 1, wxEXPAND, 5);
351 gSizerNetProps->AddSpacer(1);
352 gSizerNetProps->AddSpacer(1);
353
354 m_rbNetProtoTCP =
355 new wxRadioButton(m_scrolledwin, wxID_ANY, _("TCP"), wxDefaultPosition,
356 wxDefaultSize, wxRB_GROUP);
357 m_rbNetProtoTCP->Enable(TRUE);
358 m_rbNetProtoTCP->SetValue(TRUE);
359
360 bSizer16->Add(m_rbNetProtoTCP, 0, wxALL, 5);
361
362 m_rbNetProtoUDP = new wxRadioButton(m_scrolledwin, wxID_ANY, _("UDP"),
363 wxDefaultPosition, wxDefaultSize, 0);
364 m_rbNetProtoUDP->Enable(TRUE);
365
366 bSizer16->Add(m_rbNetProtoUDP, 0, wxALL, 5);
367
368 // Optimize for Portrait mode handheld devices
369 if (displaySize.x < displaySize.y) {
370 wxBoxSizer* bSizer16a;
371 bSizer16a = new wxBoxSizer(wxHORIZONTAL);
372 gSizerNetProps->AddSpacer(1);
373 gSizerNetProps->Add(bSizer16a, 1, wxEXPAND, 5);
374 gSizerNetProps->AddSpacer(1);
375 gSizerNetProps->AddSpacer(1);
376 m_rbNetProtoGPSD = new wxRadioButton(m_scrolledwin, wxID_ANY, _("GPSD"),
377 wxDefaultPosition, wxDefaultSize, 0);
378 m_rbNetProtoGPSD->Enable(TRUE);
379 bSizer16a->Add(m_rbNetProtoGPSD, 0, wxALL, 5);
380
381 m_rbNetProtoSignalK =
382 new wxRadioButton(m_scrolledwin, wxID_ANY, _("Signal K"),
383 wxDefaultPosition, wxDefaultSize, 0);
384 m_rbNetProtoSignalK->Enable(TRUE);
385 bSizer16a->Add(m_rbNetProtoSignalK, 0, wxALL, 5);
386 } else {
387 m_rbNetProtoGPSD = new wxRadioButton(m_scrolledwin, wxID_ANY, _("GPSD"),
388 wxDefaultPosition, wxDefaultSize, 0);
389 m_rbNetProtoGPSD->Enable(TRUE);
390 bSizer16->Add(m_rbNetProtoGPSD, 0, wxALL, 5);
391
392 m_rbNetProtoSignalK =
393 new wxRadioButton(m_scrolledwin, wxID_ANY, _("Signal K"),
394 wxDefaultPosition, wxDefaultSize, 0);
395 m_rbNetProtoSignalK->Enable(TRUE);
396 bSizer16->Add(m_rbNetProtoSignalK, 0, wxALL, 5);
397 }
398
399 m_stNetDataProtocol =
400 new wxStaticText(m_scrolledwin, wxID_ANY, _("Data Protocol"),
401 wxDefaultPosition, wxDefaultSize, 0);
402 m_stNetDataProtocol->Wrap(-1);
403
404 gSizerNetProps->Add(m_stNetDataProtocol, 0, wxALL, 5);
405
406 wxString m_choiceNetProtocolChoices[] = {_("NMEA 0183"), _("NMEA 2000")};
407 int m_choiceNetProtocolNChoices =
408 sizeof(m_choiceNetProtocolChoices) / sizeof(wxString);
409 m_choiceNetDataProtocol =
410 new wxChoice(m_scrolledwin, wxID_ANY, wxDefaultPosition, wxDefaultSize,
411 m_choiceNetProtocolNChoices, m_choiceNetProtocolChoices, 0);
412 // m_choiceNetDataProtocol->Bind(wxEVT_MOUSEWHEEL,
413 // &ConnectionEditDialog::OnWheelChoice, this);
414 m_choiceNetDataProtocol->SetSelection(0);
415 m_choiceNetDataProtocol->Enable(TRUE);
416
417 gSizerNetProps->Add(m_choiceNetDataProtocol, 1, wxEXPAND | wxTOP, 5);
418 gSizerNetProps->AddSpacer(1);
419 gSizerNetProps->AddSpacer(1);
420
421 m_stNetAddr = new wxStaticText(m_scrolledwin, wxID_ANY, _("Address"),
422 wxDefaultPosition, wxDefaultSize, 0);
423 m_stNetAddr->Wrap(-1);
424 int column1width = 16 * m_stNetProto->GetCharWidth();
425 m_stNetAddr->SetMinSize(wxSize(column1width, -1));
426 gSizerNetProps->Add(m_stNetAddr, 0, wxALL, 5);
427
428 m_tNetAddress = new wxTextCtrl(m_scrolledwin, wxID_ANY, wxEmptyString,
429 wxDefaultPosition, wxDefaultSize, 0);
430 int column2width = 40 * m_scrolledwin->GetCharWidth();
431 m_tNetAddress->SetMaxSize(wxSize(column2width, -1));
432 m_tNetAddress->SetMinSize(wxSize(column2width, -1));
433
434 gSizerNetProps->Add(m_tNetAddress, 0, wxEXPAND | wxTOP, 5);
435 gSizerNetProps->AddSpacer(1);
436 gSizerNetProps->AddSpacer(1);
437
438 m_stNetPort = new wxStaticText(m_scrolledwin, wxID_ANY, _("DataPort"),
439 wxDefaultPosition, wxDefaultSize, 0);
440 m_stNetPort->Wrap(-1);
441 gSizerNetProps->Add(m_stNetPort, 0, wxALL, 5);
442
443 m_tNetPort = new wxTextCtrl(m_scrolledwin, wxID_ANY, wxEmptyString,
444 wxDefaultPosition, wxDefaultSize, 0);
445 gSizerNetProps->Add(m_tNetPort, 1, wxEXPAND | wxTOP, 5);
446 gSizerNetProps->AddSpacer(1);
447 gSizerNetProps->AddSpacer(1);
448
449 gSizerCanProps = new wxGridSizer(0, 1, 0, 0);
450
451 wxFlexGridSizer* fgSizer1C;
452 fgSizer1C = new wxFlexGridSizer(0, 2, 0, 0);
453 // fgSizer1C->SetFlexibleDirection(wxBOTH);
454 // fgSizer1C->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
455
456 m_stCANSource =
457 new wxStaticText(m_scrolledwin, wxID_ANY, _("socketCAN Source"),
458 wxDefaultPosition, wxDefaultSize, 0);
459 m_stCANSource->Wrap(-1);
460 m_stCANSource->SetMinSize(wxSize(column1width, -1));
461 fgSizer1C->Add(m_stCANSource, 0, wxALL, 5);
462
463 wxArrayString choices = GetAvailableSocketCANInterfaces();
464 m_choiceCANSource = new wxChoice(m_scrolledwin, wxID_ANY, wxDefaultPosition,
465 wxDefaultSize, choices);
466
467 m_choiceCANSource->SetSelection(0);
468 m_choiceCANSource->Enable(TRUE);
469 m_choiceCANSource->SetMaxSize(wxSize(column2width, -1));
470 m_choiceCANSource->SetMinSize(wxSize(column2width, -1));
471 fgSizer1C->Add(m_choiceCANSource, 1, wxEXPAND | wxTOP, 5);
472
473 gSizerCanProps->Add(fgSizer1C, 0, wxEXPAND, 5);
474
475 sbSizerConnectionProps->Add(gSizerCanProps, 0, wxEXPAND, 5);
476
477 gSizerSerProps = new wxGridSizer(0, 1, 0, 0);
478 sbSizerConnectionProps->Add(gSizerSerProps, 0, wxEXPAND, 5);
479
480 wxFlexGridSizer* fgSizer1;
481 fgSizer1 = new wxFlexGridSizer(0, 4, 0, 0);
482 fgSizer1->SetFlexibleDirection(wxBOTH);
483 fgSizer1->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
484
485 m_stSerPort =
486 new wxStaticText(m_scrolledwin, wxID_ANY, _("Data port"),
487 wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
488 m_stSerPort->SetMinSize(wxSize(column1width, -1));
489 m_stSerPort->Wrap(-1);
490
491 fgSizer1->Add(m_stSerPort, 0, wxALL, 5);
492
493 m_comboPort = new wxComboBox(m_scrolledwin, wxID_ANY, wxEmptyString,
494 wxDefaultPosition, wxDefaultSize, 0, NULL, 0);
495
496 m_comboPort->SetMaxSize(wxSize(column2width, -1));
497 m_comboPort->SetMinSize(wxSize(column2width, -1));
498
499 fgSizer1->Add(m_comboPort, 0, wxEXPAND | wxTOP, 5);
500
501 m_stSerBaudrate = new wxStaticText(m_scrolledwin, wxID_ANY, _("Baudrate"),
502 wxDefaultPosition, wxDefaultSize, 0);
503 m_stSerBaudrate->Wrap(-1);
504 fgSizer1->AddSpacer(1);
505 fgSizer1->AddSpacer(1);
506 fgSizer1->Add(m_stSerBaudrate, 0, wxALL, 5);
507
508 wxString m_choiceBaudRateChoices[] = {
509 _("150"), _("300"), _("600"), _("1200"), _("2400"),
510 _("4800"), _("9600"), _("19200"), _("38400"), _("57600"),
511 _("115200"), _("230400"), _("460800"), _("921600")};
512 int m_choiceBaudRateNChoices =
513 sizeof(m_choiceBaudRateChoices) / sizeof(wxString);
514 m_choiceBaudRate =
515 new wxChoice(m_scrolledwin, wxID_ANY, wxDefaultPosition, wxDefaultSize,
516 m_choiceBaudRateNChoices, m_choiceBaudRateChoices, 0);
517 // m_choiceBaudRate->Bind(wxEVT_MOUSEWHEEL,
518 // &ConnectionEditDialog::OnWheelChoice, this);
519
520 m_choiceBaudRate->SetSelection(0);
521
522 fgSizer1->Add(m_choiceBaudRate, 1, wxEXPAND | wxTOP, 5);
523 fgSizer1->AddSpacer(1);
524 fgSizer1->AddSpacer(1);
525
526 m_stSerProtocol = new wxStaticText(m_scrolledwin, wxID_ANY, _("Protocol"),
527 wxDefaultPosition, wxDefaultSize, 0);
528 m_stSerProtocol->Wrap(-1);
529 fgSizer1->Add(m_stSerProtocol, 0, wxALL, 5);
530
531 wxString m_choiceSerialProtocolChoices[] = {_("NMEA 0183"), _("NMEA 2000")};
532 int m_choiceSerialProtocolNChoices =
533 sizeof(m_choiceSerialProtocolChoices) / sizeof(wxString);
534 m_choiceSerialProtocol = new wxChoice(
535 m_scrolledwin, wxID_ANY, wxDefaultPosition, wxDefaultSize,
536 m_choiceSerialProtocolNChoices, m_choiceSerialProtocolChoices, 0);
537 // m_choiceSerialProtocol->Bind(wxEVT_MOUSEWHEEL,
538 // &ConnectionEditDialog::OnWheelChoice, this);
539
540 m_choiceSerialProtocol->SetSelection(0);
541 m_choiceSerialProtocol->Enable(TRUE);
542 fgSizer1->Add(m_choiceSerialProtocol, 1, wxEXPAND | wxTOP, 5);
543
544 gSizerSerProps->Add(fgSizer1, 0, wxEXPAND, 5);
545
546 // User Comments
547
548 wxFlexGridSizer* commentSizer = new wxFlexGridSizer(0, 2, 0, 0);
549 // sbSizerConnectionProps->Add(commentSizer, 0, wxEXPAND, 5);
550
551 // Net User Comments
552 m_stNetComment = new wxStaticText(m_scrolledwin, wxID_ANY, _("Description"),
553 wxDefaultPosition, wxDefaultSize, 0);
554 m_stNetComment->Wrap(-1);
555 m_stNetComment->SetMinSize(wxSize(column1width, -1));
556 commentSizer->Add(m_stNetComment, 0, wxALL, 5);
557
558 m_tNetComment = new wxTextCtrl(m_scrolledwin, wxID_ANY, wxEmptyString,
559 wxDefaultPosition, wxDefaultSize, 0);
560 m_tNetComment->SetMaxSize(wxSize(column2width, -1));
561 m_tNetComment->SetMinSize(wxSize(column2width, -1));
562
563 commentSizer->Add(m_tNetComment, 1, wxEXPAND | wxTOP, 5);
564
565 // Serial User Comments
566 m_stSerialComment =
567 new wxStaticText(m_scrolledwin, wxID_ANY, _("User Comment"),
568 wxDefaultPosition, wxDefaultSize, 0);
569 m_stSerialComment->Wrap(-1);
570 m_stSerialComment->SetMinSize(wxSize(column1width, -1));
571 commentSizer->Add(m_stSerialComment, 0, wxALL, 5);
572
573 m_tSerialComment = new wxTextCtrl(m_scrolledwin, wxID_ANY, wxEmptyString,
574 wxDefaultPosition, wxDefaultSize, 0);
575 m_tSerialComment->SetMaxSize(wxSize(column2width, -1));
576 m_tSerialComment->SetMinSize(wxSize(column2width, -1));
577
578 commentSizer->Add(m_tSerialComment, 1, wxTOP, 5);
579
580 sbSizerConnectionProps->Add(commentSizer, 0, wxEXPAND, 5);
581
582 wxFlexGridSizer* fgSizer5;
583 fgSizer5 = new wxFlexGridSizer(0, 2, 0, 0);
584 fgSizer5->SetFlexibleDirection(wxBOTH);
585 fgSizer5->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
586 sbSizerConnectionProps->Add(fgSizer5, 0, wxEXPAND, 5);
587
588 m_cbInput =
589 new wxCheckBox(m_scrolledwin, wxID_ANY, _("Receive Input on this Port"),
590 wxDefaultPosition, wxDefaultSize, 0);
591 fgSizer5->Add(m_cbInput, 0, wxALL, 2);
592 fgSizer5->AddSpacer(1);
593
594 m_cbOutput =
595 new wxCheckBox(m_scrolledwin, wxID_ANY,
596 wxString::Format("%s (%s)", _("Output on this port"),
597 _("as autopilot or NMEA repeater")),
598 wxDefaultPosition, wxDefaultSize, 0);
599 fgSizer5->Add(m_cbOutput, 0, wxALL, 2);
600 fgSizer5->AddSpacer(1);
601
602 // Authentication token
603
604 m_stAuthToken = new wxStaticText(m_scrolledwin, wxID_ANY, _("Auth Token"),
605 wxDefaultPosition, wxDefaultSize, 0);
606 m_stAuthToken->SetMinSize(wxSize(column1width, -1));
607 m_stAuthToken->Wrap(-1);
608 fgSizer5->Add(m_stAuthToken, 0, wxALL, 5);
609 m_stAuthToken->Hide();
610
611 m_tAuthToken = new wxTextCtrl(m_scrolledwin, wxID_ANY, wxEmptyString,
612 wxDefaultPosition, wxDefaultSize, 0);
613 m_tAuthToken->SetMinSize(wxSize(column2width, -1));
614 fgSizer5->Add(m_tAuthToken, 1, wxEXPAND | wxTOP, 5);
615
616 m_tAuthToken->Hide();
617
618 m_cbCheckCRC = new wxCheckBox(m_scrolledwin, wxID_ANY, _("Control checksum"),
619 wxDefaultPosition, wxDefaultSize, 0);
620 m_cbCheckCRC->SetValue(TRUE);
621 m_cbCheckCRC->SetToolTip(
622 _("If checked, only the sentences with a valid checksum are passed "
623 "through"));
624 fgSizer5->Add(m_cbCheckCRC, 0, wxALL, 2);
625 fgSizer5->AddSpacer(1);
626
627 m_cbGarminHost = new wxCheckBox(m_scrolledwin, wxID_ANY,
628 _("Use Garmin (GRMN) mode for input"),
629 wxDefaultPosition, wxDefaultSize, 0);
630 m_cbGarminHost->SetValue(FALSE);
631 fgSizer5->Add(m_cbGarminHost, 0, wxALL, 2);
632 fgSizer5->AddSpacer(1);
633
634#ifndef USE_GARMINHOST
635 m_cbGarminHost->Hide();
636#endif
637
638 m_cbMultiCast = new wxCheckBox(m_scrolledwin, wxID_ANY, _(" UDP Multicast"),
639 wxDefaultPosition, wxDefaultSize, 0);
640 m_cbMultiCast->SetValue(FALSE);
641 // m_cbMultiCast->SetToolTip(_("Advanced Use Only. Enable UDP Multicast."));
642
643 fgSizer5->Add(m_cbMultiCast, 0, wxALL, 2);
644 fgSizer5->AddSpacer(1);
645
646 m_stPrecision =
647 new wxStaticText(m_scrolledwin, wxID_ANY, _("APB bearing precision"),
648 wxDefaultPosition, wxDefaultSize, 0);
649
650 m_stPrecision->Wrap(-1);
651 fgSizer5->Add(m_stPrecision, 0, wxALL, 2);
652
653 wxString m_choicePrecisionChoices[] = {_("x"), _("x.x"), _("x.xx"),
654 _("x.xxx"), _("x.xxxx")};
655 int m_choicePrecisionNChoices =
656 sizeof(m_choicePrecisionChoices) / sizeof(wxString);
657 m_choicePrecision =
658 new wxChoice(m_scrolledwin, wxID_ANY, wxDefaultPosition, wxDefaultSize,
659 m_choicePrecisionNChoices, m_choicePrecisionChoices, 0);
660 // m_choicePrecision->Bind(wxEVT_MOUSEWHEEL,
661 // &ConnectionEditDialog::OnWheelChoice, this);
662
663 m_choicePrecision->SetSelection(g_NMEAAPBPrecision);
664 fgSizer5->Add(m_choicePrecision, 0, wxALL, 2);
665
666 // signalK discovery enable
667 m_cbCheckSKDiscover =
668 new wxCheckBox(m_scrolledwin, wxID_ANY, _("Automatic server discovery"),
669 wxDefaultPosition, wxDefaultSize, 0);
670 m_cbCheckSKDiscover->SetValue(TRUE);
671 m_cbCheckSKDiscover->SetToolTip(
672 _("If checked, signal K server will be discovered automatically"));
673
674 fgSizer5->Add(m_cbCheckSKDiscover, 0, wxALL, 2);
675
676 // signal K "Discover now" button
677 m_ButtonSKDiscover =
678 new wxButton(m_scrolledwin, wxID_ANY, _("Discover now..."),
679 wxDefaultPosition, wxDefaultSize, 0);
680 m_ButtonSKDiscover->Hide();
681 fgSizer5->Add(m_ButtonSKDiscover, 0, wxALL, 2);
682
683 // signalK Server Status
684 m_StaticTextSKServerStatus = new wxStaticText(
685 m_scrolledwin, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, 0);
686 fgSizer5->Add(m_StaticTextSKServerStatus, 0, wxALL, 2);
687
688 sbSizerInFilter = new wxStaticBoxSizer(
689 new wxStaticBox(m_scrolledwin, wxID_ANY, _("Input filtering")),
690 wxVERTICAL);
691 sbSizerConnectionProps->Add(sbSizerInFilter,
692 wxSizerFlags().Expand().Border());
693
694 wxBoxSizer* bSizer9;
695 bSizer9 = new wxBoxSizer(wxHORIZONTAL);
696
697 m_rbIAccept =
698 new wxRadioButton(m_scrolledwin, wxID_ANY, _("Accept only sentences"),
699 wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
700 bSizer9->Add(m_rbIAccept, 0, wxALL, 5);
701
702 m_rbIIgnore =
703 new wxRadioButton(m_scrolledwin, wxID_ANY, _("Ignore sentences"),
704 wxDefaultPosition, wxDefaultSize, 0);
705 bSizer9->Add(m_rbIIgnore, 0, wxALL, 5);
706
707 sbSizerInFilter->Add(bSizer9, 0, wxEXPAND, 5);
708
709 wxBoxSizer* bSizer11;
710 bSizer11 = new wxBoxSizer(wxHORIZONTAL);
711 sbSizerInFilter->Add(bSizer11, 0, wxEXPAND, 5);
712
713 m_tcInputStc =
714 new wxTextCtrl(m_scrolledwin, wxID_ANY, wxEmptyString, wxDefaultPosition,
715 wxDefaultSize, wxTE_READONLY);
716 bSizer11->Add(m_tcInputStc, 1, wxALL | wxEXPAND, 5);
717
718 m_btnInputStcList =
719 new wxButton(m_scrolledwin, wxID_ANY, "...", wxDefaultPosition,
720 wxDefaultSize, wxBU_EXACTFIT);
721 bSizer11->Add(m_btnInputStcList, 0, wxALL, 5);
722
723 bSizer11->AddSpacer(GetCharWidth() * 5);
724
725 sbSizerOutFilter = new wxStaticBoxSizer(
726 new wxStaticBox(m_scrolledwin, wxID_ANY, _("Output filtering")),
727 wxVERTICAL);
728 sbSizerConnectionProps->Add(sbSizerOutFilter, 0, wxEXPAND, 5);
729
730 wxBoxSizer* bSizer10;
731 bSizer10 = new wxBoxSizer(wxHORIZONTAL);
732
733 m_rbOAccept =
734 new wxRadioButton(m_scrolledwin, wxID_ANY, _("Transmit sentences"),
735 wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
736 bSizer10->Add(m_rbOAccept, 0, wxALL, 5);
737
738 m_rbOIgnore = new wxRadioButton(m_scrolledwin, wxID_ANY, _("Drop sentences"),
739 wxDefaultPosition, wxDefaultSize, 0);
740 bSizer10->Add(m_rbOIgnore, 0, wxALL, 5);
741
742 sbSizerOutFilter->Add(bSizer10, 0, wxEXPAND, 5);
743
744 wxBoxSizer* bSizer12;
745 bSizer12 = new wxBoxSizer(wxHORIZONTAL);
746 sbSizerOutFilter->Add(bSizer12, 0, wxEXPAND, 5);
747
748 m_tcOutputStc =
749 new wxTextCtrl(m_scrolledwin, wxID_ANY, wxEmptyString, wxDefaultPosition,
750 wxDefaultSize, wxTE_READONLY);
751 bSizer12->Add(m_tcOutputStc, 1, wxALL | wxEXPAND, 5);
752
753 m_btnOutputStcList =
754 new wxButton(m_scrolledwin, wxID_ANY, "...", wxDefaultPosition,
755 wxDefaultSize, wxBU_EXACTFIT);
756 bSizer12->Add(m_btnOutputStcList, 0, wxALL, 5);
757
758 bSizer12->AddSpacer(GetCharWidth() * 5);
759
760 sbSizerConnectionProps->AddSpacer(20);
761
762 m_more = new wxStaticText(m_scrolledwin, wxID_ANY, "4 chars",
763 wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
764 m_more->SetLabelMarkup(MORE);
765 sbSizerConnectionProps->Add(m_more, wxSizerFlags().Border());
766
767 ConnectControls();
768
769 SetInitialSettings();
770
771 ShowTypeCommon();
772
773 ShowNMEACommon(true);
774 ShowNMEASerial(true);
775 ShowNMEANet(false);
776 ShowNMEACAN(false);
777 connectionsaved = TRUE;
778
779 GetSizer()->Fit(m_scrolledwin);
780
781 new_device_listener.Init(SystemEvents::GetInstance().evt_dev_change,
782 [&](ObservedEvt&) { LoadSerialPorts(m_comboPort); });
783}
784
785// void ConnectionEditDialog::OnWheelChoice(wxMouseEvent& event) {
786// return;
787// }
788
789void ConnectionEditDialog::SetSelectedConnectionPanel(
790 ConnectionParamsPanel* panel) {
791 // Only one panel can be selected at any time
792 // Clear any selections
793
794 if (mSelectedConnection && mSelectedConnection->m_optionsPanel)
795 mSelectedConnection->m_optionsPanel->SetSelected(false);
796
797 if (panel) {
798 mSelectedConnection = panel->m_pConnectionParams;
799 panel->SetSelected(true);
800 SetConnectionParams(mSelectedConnection);
801 m_buttonRemove->Enable();
802 m_buttonRemove->Show();
803 m_buttonAdd->Disable();
804 m_sbConnEdit->SetLabel(_("Edit Selected Connection"));
805
806 } else {
807 mSelectedConnection = NULL;
808 m_buttonRemove->Disable();
809 m_buttonAdd->Enable();
810 m_buttonAdd->Show();
811 m_sbConnEdit->SetLabel("");
812 ClearNMEAForm();
813 }
814
815 // Scroll the panel to allow the user to see more of the NMEA parameter
816 // settings area
817 // wxPoint buttonPosition = m_buttonAdd->GetPosition();
818 // this->Scroll(-1, buttonPosition.y / m_parent->GetScrollRate());
819}
820
821void ConnectionEditDialog::SetPropsLabel(wxString label) {
822 m_sbConnEdit->SetLabel(label);
823}
824
825void ConnectionEditDialog::EnableConnection(ConnectionParams* conn,
826 bool value) {
827 if (conn) {
828 // conn->bEnabled = value;
829 conn->b_IsSetup = FALSE; // trigger a rebuild/takedown of the connection
830 m_connection_enabled = conn->bEnabled;
831 }
832}
833
834#if 1
835void ConnectionEditDialog::OnValChange(wxCommandEvent& event) { event.Skip(); }
836
837void ConnectionEditDialog::OnScanBTClick(wxCommandEvent& event) {
838 if (m_BTscanning)
839 StopBTScan();
840 else {
841 m_btNoChangeCounter = 0;
842 m_btlastResultCount = 0;
843
844 m_BTScanTimer.Start(1000, wxTIMER_CONTINUOUS);
845 g_Platform->startBluetoothScan();
846 m_BTscanning = 1;
847 if (m_buttonScanBT) {
848 m_buttonScanBT->SetLabel(_("Stop Scan"));
849 }
850 }
851}
852
853void ConnectionEditDialog::onBTScanTimer(wxTimerEvent& event) {
854 if (m_BTscanning) {
855 m_BTscanning++;
856
857 m_BTscan_results = g_Platform->getBluetoothScanResults();
858
859 m_choiceBTDataSources->Clear();
860 m_choiceBTDataSources->Append(m_BTscan_results[0]); // scan status
861
862 unsigned int i = 1;
863 while ((i + 1) < m_BTscan_results.GetCount()) {
864 wxString item1 = m_BTscan_results[i] + ";";
865 wxString item2 = m_BTscan_results.Item(i + 1);
866 m_choiceBTDataSources->Append(item1 + item2);
867
868 i += 2;
869 }
870
871 if (m_BTscan_results.GetCount() > 1) {
872 m_choiceBTDataSources->SetSelection(1);
873 }
874
875 // Watch for changes. When no changes occur after n seconds, stop the scan
876 if (m_btNoChangeCounter > 5) StopBTScan();
877
878 if ((int)m_BTscan_results.GetCount() == m_btlastResultCount)
879 m_btNoChangeCounter++;
880 else
881 m_btNoChangeCounter = 0;
882
883 m_btlastResultCount = m_BTscan_results.GetCount();
884
885 // Absolute fallback
886 if (m_BTscanning >= 15) {
887 StopBTScan();
888 }
889 } else {
890 }
891 return;
892}
893
894void ConnectionEditDialog::StopBTScan(void) {
895 m_BTScanTimer.Stop();
896
897 g_Platform->stopBluetoothScan();
898
899 m_BTscanning = 0;
900
901 if (m_buttonScanBT) {
902 m_buttonScanBT->SetLabel(_("BT Scan"));
903 m_buttonScanBT->Enable();
904 }
905}
906
907void ConnectionEditDialog::OnConnValChange(wxCommandEvent& event) {
908 connectionsaved = FALSE;
909 event.Skip();
910}
911
912void ConnectionEditDialog::OnTypeSerialSelected(wxCommandEvent& event) {
913 OnConnValChange(event);
914 SetNMEAFormToSerial();
915}
916
917void ConnectionEditDialog::OnTypeNetSelected(wxCommandEvent& event) {
918 OnConnValChange(event);
919 SetNMEAFormToNet();
920}
921
922void ConnectionEditDialog::OnTypeCANSelected(wxCommandEvent& event) {
923 OnConnValChange(event);
924 SetNMEAFormToCAN();
925}
926
927void ConnectionEditDialog::OnTypeGPSSelected(wxCommandEvent& event) {
928 OnConnValChange(event);
929 SetNMEAFormToGPS();
930}
931
932void ConnectionEditDialog::OnTypeBTSelected(wxCommandEvent& event) {
933 OnConnValChange(event);
934 SetNMEAFormToBT();
935}
936
937void ConnectionEditDialog::OnUploadFormatChange(wxCommandEvent& event) {
938 if (event.GetEventObject() == m_cbGarminUploadHost && event.IsChecked())
939 m_cbFurunoGP3X->SetValue(FALSE);
940 else if (event.GetEventObject() == m_cbFurunoGP3X && event.IsChecked())
941 m_cbGarminUploadHost->SetValue(FALSE);
942
943 OnConnValChange(event);
944 event.Skip();
945}
946#endif
947
948void ConnectionEditDialog::ShowTypeCommon(bool visible) {
949 m_rbTypeSerial->Show(visible);
950 m_rbTypeNet->Show(visible);
951#if defined(__linux__) && !defined(__ANDROID__) && !defined(__WXOSX__)
952 m_rbTypeCAN->Show(visible);
953#endif
954 if (m_rbTypeInternalGPS) m_rbTypeInternalGPS->Show(visible);
955 if (m_rbTypeInternalBT) m_rbTypeInternalBT->Show(visible);
956}
957
958void ConnectionEditDialog::ShowNMEACommon(bool visible) {
959 bool advanced = m_advanced;
960 m_cbInput->Show(visible);
961 m_cbOutput->Show(visible);
962 m_stPrecision->Show(visible && advanced);
963 m_choicePrecision->Show(visible && advanced);
964 m_stPrecision->Show(visible && advanced);
965 m_cbCheckCRC->Show(visible && advanced);
966 m_stAuthToken->Show(visible && advanced);
967 m_tAuthToken->Show(visible && advanced);
968 if (visible) {
969 const bool bout_enable = (m_cbOutput->IsChecked() && advanced);
970 m_stPrecision->Enable(bout_enable);
971 m_choicePrecision->Enable(bout_enable);
972 } else {
973 sbSizerOutFilter->SetDimension(0, 0, 0, 0);
974 sbSizerInFilter->SetDimension(0, 0, 0, 0);
975 sbSizerConnectionProps->SetDimension(0, 0, 0, 0);
976 m_sbConnEdit->SetLabel("");
977 }
978
979 m_cbCheckSKDiscover->Hide(); // Provisional
980 m_ButtonSKDiscover->Hide();
981
982 const bool bin_enable = (m_cbInput->IsChecked() && advanced);
983 ShowInFilter(visible && bin_enable);
984 const bool bout_enable = (m_cbOutput->IsChecked() && advanced);
985 ShowOutFilter(visible && bout_enable);
986
987 m_bNMEAParams_shown = visible;
988}
989
990void ConnectionEditDialog::ShowNMEANet(bool visible) {
991 bool advanced = m_advanced;
992 m_stNetAddr->Show(visible);
993 m_tNetAddress->Show(visible);
994 m_stNetDataProtocol->Show(visible);
995 m_stNetPort->Show(visible);
996 m_choiceNetDataProtocol->Show(visible);
997 m_tNetPort->Show(visible);
998 m_stNetProto->Show(visible);
999 m_rbNetProtoSignalK->Show(visible);
1000 m_rbNetProtoGPSD->Show(visible);
1001 m_rbNetProtoTCP->Show(visible);
1002 m_rbNetProtoUDP->Show(visible);
1003 m_stNetComment->Show(visible);
1004 m_tNetComment->Show(visible);
1005 m_stAuthToken->Show(visible);
1006 m_tAuthToken->Show(visible);
1007 m_cbGarminHost->Hide();
1008}
1009
1010void ConnectionEditDialog::ShowNMEASerial(bool visible) {
1011 bool advanced = m_advanced;
1012 m_stSerBaudrate->Show(visible);
1013 m_choiceBaudRate->Show(visible);
1014 m_stSerPort->Show(visible);
1015 m_comboPort->Show(visible);
1016 m_stSerProtocol->Show(visible);
1017 m_choiceSerialProtocol->Show(visible);
1018 m_cbGarminHost->Show(visible && advanced);
1019 m_stSerialComment->Show(visible);
1020 m_tSerialComment->Show(visible);
1021}
1022
1023void ConnectionEditDialog::ShowNMEAGPS(bool visible) {
1024 m_cbCheckSKDiscover->Hide();
1025 m_ButtonSKDiscover->Hide();
1026 m_stAuthToken->Hide();
1027 m_tAuthToken->Hide();
1028 m_cbOutput->Hide();
1029}
1030
1031void ConnectionEditDialog::ShowNMEACAN(bool visible) {
1032 m_stCANSource->Show(visible);
1033 m_choiceCANSource->Show(visible);
1034}
1035
1036void ConnectionEditDialog::ShowNMEABT(bool visible) {
1037 if (visible) {
1038 if (m_buttonScanBT) m_buttonScanBT->Show();
1039 if (m_stBTPairs) m_stBTPairs->Show();
1040 if (m_choiceBTDataSources) {
1041 if (m_choiceBTDataSources->GetCount() > 1)
1042 m_choiceBTDataSources->SetSelection(1);
1043 m_choiceBTDataSources->Show();
1044 }
1045 } else {
1046 if (m_buttonScanBT) m_buttonScanBT->Hide();
1047 if (m_stBTPairs) m_stBTPairs->Hide();
1048 if (m_choiceBTDataSources) m_choiceBTDataSources->Hide();
1049 }
1050 m_cbCheckSKDiscover->Hide();
1051 m_stAuthToken->Hide();
1052 m_tAuthToken->Hide();
1053 m_cbCheckSKDiscover->Hide(); // Provisional
1054 m_ButtonSKDiscover->Hide();
1055 m_tcOutputStc->Show(visible);
1056 m_btnOutputStcList->Show(visible);
1057 m_cbOutput->Show(visible);
1058}
1059
1060void ConnectionEditDialog::SetNMEAFormToSerial(void) {
1061 bool advanced = m_advanced;
1062 ShowNMEACommon(TRUE);
1063 ShowNMEANet(FALSE);
1064 ShowNMEAGPS(FALSE);
1065 ShowNMEABT(FALSE);
1066 ShowNMEASerial(TRUE);
1067 ShowNMEACAN(FALSE);
1068 SetDSFormRWStates();
1069 LayoutDialog();
1070}
1071
1072void ConnectionEditDialog::SetNMEAFormToNet(void) {
1073 bool advanced = m_advanced;
1074 ShowNMEACommon(TRUE);
1075 ShowNMEANet(TRUE);
1076 ShowNMEAGPS(FALSE);
1077 ShowNMEABT(FALSE);
1078 ShowNMEASerial(FALSE);
1079 ShowNMEACAN(FALSE);
1080 SetUDPNetAddressVisiblity();
1081 SetDSFormRWStates();
1082
1083 LayoutDialog();
1084}
1085
1086void ConnectionEditDialog::SetNMEAFormToCAN(void) {
1087 bool advanced = m_advanced;
1088 ShowNMEACommon(FALSE);
1089 ShowNMEANet(FALSE);
1090 ShowNMEAGPS(FALSE);
1091 ShowNMEABT(FALSE);
1092 ShowNMEASerial(FALSE);
1093 ShowNMEACAN(TRUE);
1094 sbSizerInFilter->Show(false);
1095 sbSizerOutFilter->Show(false);
1096 SetDSFormRWStates();
1097
1098 LayoutDialog();
1099}
1100
1101void ConnectionEditDialog::SetNMEAFormToGPS(void) {
1102 ShowNMEACommon(TRUE);
1103 ShowNMEANet(FALSE);
1104 ShowNMEAGPS(TRUE);
1105 ShowNMEABT(FALSE);
1106 ShowNMEASerial(FALSE);
1107 ShowNMEACAN(FALSE);
1108
1109 // m_container->FitInside();
1110 // Fit();
1111 SetDSFormRWStates();
1112 LayoutDialog();
1113}
1114
1115void ConnectionEditDialog::SetNMEAFormToBT(void) {
1116 m_rbNetProtoUDP->SetValue(true);
1117 ShowNMEACommon(TRUE);
1118 ShowNMEANet(FALSE);
1119 ShowNMEAGPS(FALSE);
1120 ShowNMEABT(TRUE);
1121 ShowNMEASerial(FALSE);
1122 ShowNMEACAN(FALSE);
1123
1124 // m_container->FitInside();
1125 // Fit();
1126 SetDSFormRWStates();
1127 LayoutDialog();
1128}
1129
1130void ConnectionEditDialog::ClearNMEAForm(void) {
1131 ShowNMEACommon(FALSE);
1132 ShowNMEANet(FALSE);
1133 ShowNMEAGPS(FALSE);
1134 ShowNMEABT(FALSE);
1135 ShowNMEASerial(FALSE);
1136 ShowNMEACAN(FALSE);
1137
1138 // m_container->FitInside();
1139 // Fit();
1140}
1141
1142void ConnectionEditDialog::SetDSFormOptionVizStates(void) {
1143 bool advanced = m_advanced;
1144 m_more->Show(true);
1145 m_cbInput->Show();
1146 m_cbOutput->Show();
1147 m_cbCheckCRC->Show(advanced);
1148 m_stPrecision->Show(true);
1149 m_choicePrecision->Show(true);
1150
1151 ShowInFilter(advanced);
1152 ShowOutFilter(advanced);
1153 // Discovery hidden until it works.
1154 // m_cbCheckSKDiscover->Show();
1155 m_stAuthToken->Show(advanced);
1156 m_tAuthToken->Show(advanced);
1157 // m_ButtonSKDiscover->Show();
1158 m_StaticTextSKServerStatus->Show(advanced);
1159
1160 if (m_rbTypeSerial->GetValue()) {
1161 m_cbMultiCast->Hide();
1162 m_cbCheckSKDiscover->Hide();
1163 m_stAuthToken->Hide();
1164 m_tAuthToken->Hide();
1165 m_ButtonSKDiscover->Hide();
1166 m_StaticTextSKServerStatus->Hide();
1167 bool n0183ctlenabled =
1168 (DataProtocol)m_choiceSerialProtocol->GetSelection() ==
1169 DataProtocol::PROTO_NMEA0183;
1170 if (!n0183ctlenabled) {
1171 m_cbInput->Hide();
1172 m_cbOutput->Hide();
1173 ShowOutFilter(false);
1174 ShowInFilter(false);
1175 m_stPrecision->Hide();
1176 m_choicePrecision->Hide();
1177 m_cbCheckCRC->Hide();
1178 m_stNetDataProtocol->Hide();
1179 m_choiceNetDataProtocol->Hide();
1180 } else {
1181 m_cbInput->Show();
1182 m_cbInput->Enable();
1183
1184 ShowInFilter(m_cbInput->IsChecked() && advanced);
1185 ShowOutFilter(m_cbOutput->IsChecked() && advanced);
1186
1187 m_stPrecision->Show(m_cbOutput->IsChecked() && advanced);
1188 m_choicePrecision->Show(m_cbOutput->IsChecked() && advanced);
1189
1190 m_cbGarminHost->Show(m_cbInput->IsChecked() && advanced);
1191 }
1192 }
1193
1194 if (m_rbTypeInternalGPS && m_rbTypeInternalGPS->GetValue()) {
1195 m_cbMultiCast->Hide();
1196 m_cbCheckSKDiscover->Hide();
1197 m_stAuthToken->Hide();
1198 m_tAuthToken->Hide();
1199 m_ButtonSKDiscover->Hide();
1200 m_StaticTextSKServerStatus->Hide();
1201 m_cbOutput->Hide();
1202 m_cbInput->Hide();
1203 ShowOutFilter(false);
1204 ShowInFilter(false);
1205 m_stPrecision->Hide();
1206 m_choicePrecision->Hide();
1207 m_cbCheckCRC->Hide();
1208 m_cbGarminHost->Hide();
1209 m_more->Hide();
1210 }
1211
1212 if (m_rbTypeInternalBT && m_rbTypeInternalBT->GetValue()) {
1213 m_cbMultiCast->Hide();
1214 m_cbCheckSKDiscover->Hide();
1215 m_stAuthToken->Hide();
1216 m_tAuthToken->Hide();
1217 m_ButtonSKDiscover->Hide();
1218 m_StaticTextSKServerStatus->Hide();
1219
1220 ShowInFilter(m_cbInput->IsChecked() && advanced);
1221 ShowOutFilter(m_cbOutput->IsChecked() && advanced);
1222
1223 m_stPrecision->Show(m_cbOutput->IsChecked() && advanced);
1224 m_choicePrecision->Show(m_cbOutput->IsChecked() && advanced);
1225 }
1226
1227 if (m_rbTypeCAN->GetValue()) {
1228 m_cbMultiCast->Hide();
1229 m_cbCheckSKDiscover->Hide();
1230 m_stAuthToken->Hide();
1231 m_tAuthToken->Hide();
1232 m_ButtonSKDiscover->Hide();
1233 m_StaticTextSKServerStatus->Hide();
1234 m_cbGarminHost->Hide();
1235 m_cbInput->Hide();
1236 m_cbOutput->Hide();
1237
1238 ShowInFilter(false);
1239 ShowOutFilter(false);
1240
1241 m_stPrecision->Hide();
1242 m_choicePrecision->Hide();
1243 m_cbCheckCRC->Hide();
1244
1245 m_stNetDataProtocol->Hide();
1246 m_choiceNetDataProtocol->Hide();
1247 m_more->Hide();
1248 }
1249
1250 if (m_rbTypeNet->GetValue()) {
1251 if (m_rbNetProtoGPSD->GetValue()) {
1252 m_cbMultiCast->Hide();
1253 m_cbCheckSKDiscover->Hide();
1254 m_cbInput->Hide();
1255 m_cbOutput->Hide();
1256 ShowInFilter(false);
1257 ShowOutFilter(false);
1258 m_cbCheckCRC->Hide();
1259 m_stPrecision->Hide();
1260 m_choicePrecision->Hide();
1261 m_ButtonSKDiscover->Hide();
1262 m_StaticTextSKServerStatus->Hide();
1263 m_stAuthToken->Hide();
1264 m_tAuthToken->Hide();
1265 m_stNetDataProtocol->Hide();
1266 m_choiceNetDataProtocol->Hide();
1267 m_cbGarminHost->Hide();
1268 m_more->Hide();
1269
1270 } else if (m_rbNetProtoSignalK->GetValue()) {
1271 m_cbMultiCast->Hide();
1272 m_cbInput->Hide();
1273 m_cbOutput->Hide();
1274 ShowInFilter(false);
1275 ShowOutFilter(false);
1276 m_cbCheckCRC->Hide();
1277 m_stPrecision->Hide();
1278 m_choicePrecision->Hide();
1279 m_stNetDataProtocol->Hide();
1280 m_choiceNetDataProtocol->Hide();
1281 m_cbGarminHost->Hide();
1282
1283 } else { // tcp or udp
1284 m_stAuthToken->Hide();
1285 m_tAuthToken->Hide();
1286 m_cbCheckSKDiscover->Hide();
1287 m_ButtonSKDiscover->Hide();
1288 m_StaticTextSKServerStatus->Hide();
1289 m_stNetDataProtocol->Show();
1290 m_choiceNetDataProtocol->Show();
1291 m_cbGarminHost->Hide();
1292
1293 // if (m_rbNetProtoUDP->GetValue()) m_cbMultiCast->Show(advanced);
1294
1295 if ((DataProtocol)m_choiceNetDataProtocol->GetSelection() ==
1296 DataProtocol::PROTO_NMEA2000) {
1297 m_cbCheckCRC->Hide();
1298 m_stPrecision->Hide();
1299 m_choicePrecision->Hide();
1300
1301 ShowInFilter(false);
1302 ShowOutFilter(false);
1303 if (m_rbNetProtoTCP->GetValue()) m_more->Hide();
1304 }
1305 if ((DataProtocol)m_choiceNetDataProtocol->GetSelection() ==
1306 DataProtocol::PROTO_NMEA0183) {
1307 m_stPrecision->Show(advanced);
1308 m_choicePrecision->Show(advanced);
1309 m_stPrecision->Enable(m_cbOutput->IsChecked() && advanced);
1310 m_choicePrecision->Enable(m_cbOutput->IsChecked() && advanced);
1311
1312 ShowInFilter(m_cbInput->IsChecked() && advanced);
1313 ShowOutFilter(m_cbOutput->IsChecked() && advanced);
1314 }
1315 }
1316 }
1317}
1318
1319void ConnectionEditDialog::SetDSFormRWStates(void) {
1320 if (m_rbTypeSerial->GetValue()) {
1321 m_cbInput->Enable(FALSE);
1322 m_cbOutput->Enable(TRUE);
1323 ShowInFilter();
1324 ShowOutFilter(m_cbOutput->IsChecked());
1325 } else if (m_rbNetProtoGPSD->GetValue()) {
1326 if (m_tNetPort->GetValue() == wxEmptyString)
1327 m_tNetPort->SetValue(DEFAULT_GPSD_PORT);
1328 m_cbInput->SetValue(TRUE);
1329 m_cbInput->Enable(FALSE);
1330 // m_cbOutput->SetValue(FALSE);
1331 m_cbOutput->Enable(FALSE);
1332 m_rbOAccept->Enable(FALSE);
1333 m_rbOIgnore->Enable(FALSE);
1334 m_btnOutputStcList->Enable(FALSE);
1335 } else if (m_rbNetProtoSignalK->GetValue()) {
1336 if (m_tNetPort->GetValue() == wxEmptyString)
1337 m_tNetPort->SetValue(DEFAULT_SIGNALK_PORT);
1338 m_cbInput->SetValue(TRUE);
1339 m_cbInput->Enable(FALSE);
1340 // m_cbOutput->SetValue(FALSE);
1341 m_cbOutput->Enable(FALSE);
1342 m_rbOAccept->Enable(FALSE);
1343 m_rbOIgnore->Enable(FALSE);
1344 UpdateDiscoverStatus(wxEmptyString);
1345 } else {
1346 if (m_tNetPort->GetValue() == wxEmptyString) {
1347 if (m_rbNetProtoTCP->GetValue()) {
1348 m_tNetPort->SetValue(DEFAULT_TCP_PORT);
1349 } else {
1350 m_tNetPort->SetValue(DEFAULT_UDP_PORT);
1351 }
1352 }
1353 m_cbInput->Enable(TRUE);
1354 m_cbOutput->Enable(TRUE);
1355 m_rbOAccept->Enable(TRUE);
1356 m_rbOIgnore->Enable(TRUE);
1357 m_btnOutputStcList->Enable(TRUE);
1358 }
1359
1360 SetDSFormOptionVizStates();
1361 // m_container->FitInside();
1362}
1363
1364void ConnectionEditDialog::ShowInFilter(bool bshow) {
1365 sbSizerInFilter->GetStaticBox()->Show(bshow);
1366 m_rbIAccept->Show(bshow);
1367 m_rbIIgnore->Show(bshow);
1368 m_tcInputStc->Show(bshow);
1369 m_btnInputStcList->Show(bshow);
1370}
1371
1372void ConnectionEditDialog::ShowOutFilter(bool bshow) {
1373 sbSizerOutFilter->GetStaticBox()->Show(bshow);
1374 m_rbOAccept->Show(bshow);
1375 m_rbOIgnore->Show(bshow);
1376 m_tcOutputStc->Show(bshow);
1377 m_btnOutputStcList->Show(bshow);
1378}
1379
1380void ConnectionEditDialog::PreloadControls(ConnectionParams* cp) {
1381 SetConnectionParams(cp);
1382}
1383
1384void ConnectionEditDialog::SetConnectionParams(ConnectionParams* cp) {
1385 if (wxNOT_FOUND == m_comboPort->FindString(cp->Port))
1386 m_comboPort->Append(cp->Port);
1387
1388 m_comboPort->Select(m_comboPort->FindString(cp->Port));
1389
1390 m_cbCheckCRC->SetValue(cp->ChecksumCheck);
1391 m_cbGarminHost->SetValue(cp->Garmin);
1392 m_cbInput->SetValue(cp->IOSelect != DS_TYPE_OUTPUT);
1393 m_cbOutput->SetValue(cp->IOSelect != DS_TYPE_INPUT);
1394 m_cbCheckSKDiscover->SetValue(cp->AutoSKDiscover);
1395
1396 if (cp->InputSentenceListType == WHITELIST)
1397 m_rbIAccept->SetValue(TRUE);
1398 else
1399 m_rbIIgnore->SetValue(TRUE);
1400 if (cp->OutputSentenceListType == WHITELIST)
1401 m_rbOAccept->SetValue(TRUE);
1402 else
1403 m_rbOIgnore->SetValue(TRUE);
1404 m_tcInputStc->SetValue(StringArrayToString(cp->InputSentenceList));
1405 m_tcOutputStc->SetValue(StringArrayToString(cp->OutputSentenceList));
1406 m_choiceBaudRate->Select(
1407 m_choiceBaudRate->FindString(wxString::Format("%d", cp->Baudrate)));
1408 m_choiceSerialProtocol->Select(cp->Protocol); // TODO
1409 m_tNetAddress->SetValue(cp->NetworkAddress);
1410
1411 m_choiceNetDataProtocol->Select(cp->Protocol); // TODO
1412
1413 m_cbMultiCast->SetValue(IsAddressMultiCast(m_tNetAddress->GetValue()));
1414
1415 if (cp->NetworkPort == 0)
1416 m_tNetPort->SetValue(wxEmptyString);
1417 else
1418 m_tNetPort->SetValue(wxString::Format(wxT("%i"), cp->NetworkPort));
1419
1420 if (cp->NetProtocol == TCP)
1421 m_rbNetProtoTCP->SetValue(TRUE);
1422 else if (cp->NetProtocol == UDP)
1423 m_rbNetProtoUDP->SetValue(TRUE);
1424 else if (cp->NetProtocol == GPSD)
1425 m_rbNetProtoGPSD->SetValue(TRUE);
1426 else if (cp->NetProtocol == SIGNALK)
1427 m_rbNetProtoSignalK->SetValue(TRUE);
1428 else
1429 m_rbNetProtoGPSD->SetValue(TRUE);
1430
1431 if (cp->Type == SERIAL) {
1432 m_rbTypeSerial->SetValue(TRUE);
1433 SetNMEAFormToSerial();
1434 SetNMEAFormForSerialProtocol();
1435 } else if (cp->Type == NETWORK) {
1436 m_rbTypeNet->SetValue(TRUE);
1437 SetNMEAFormToNet();
1438 } else if (cp->Type == SOCKETCAN) {
1439 m_rbTypeCAN->SetValue(TRUE);
1440 SetNMEAFormToCAN();
1441
1442 } else if (cp->Type == INTERNAL_GPS) {
1443 if (m_rbTypeInternalGPS) m_rbTypeInternalGPS->SetValue(TRUE);
1444 SetNMEAFormToGPS();
1445 } else if (cp->Type == INTERNAL_BT) {
1446 if (m_rbTypeInternalBT) m_rbTypeInternalBT->SetValue(TRUE);
1447 SetNMEAFormToBT();
1448
1449 // Preset the source selector
1450 wxString bts = cp->NetworkAddress + ";" + cp->GetPortStr();
1451 m_choiceBTDataSources->Clear();
1452 m_choiceBTDataSources->Append(bts);
1453 m_choiceBTDataSources->SetSelection(0);
1454 } else
1455 ClearNMEAForm();
1456
1457 if (cp->Type == SERIAL)
1458 m_tSerialComment->SetValue(cp->UserComment);
1459 else if (cp->Type == NETWORK)
1460 m_tNetComment->SetValue(cp->UserComment);
1461
1462 m_tAuthToken->SetValue(cp->AuthToken);
1463
1464 m_connection_enabled = cp->bEnabled;
1465
1466 // Reset touch flag
1467 connectionsaved = true;
1468}
1469
1470void ConnectionEditDialog::SetUDPNetAddressVisiblity(void) {
1471 if (m_rbNetProtoUDP->GetValue() && !m_cbMultiCast->IsChecked() &&
1472 !m_cbOutput->IsChecked()) {
1473 // m_stNetAddr->Show(FALSE);
1474 // m_tNetAddress->Show(FALSE);
1475 m_tNetAddress->Enable(TRUE);
1476 } else {
1477 m_stNetAddr->Show(TRUE);
1478 m_tNetAddress->Show(TRUE);
1479 m_tNetAddress->Enable(TRUE);
1480 }
1481 if (!m_rbNetProtoUDP->GetValue()) {
1482 m_stNetAddr->Show(TRUE);
1483 m_tNetAddress->Show(TRUE);
1484 m_tNetAddress->Enable(TRUE);
1485 }
1486 if (m_rbNetProtoUDP->GetValue() && m_advanced) {
1487 // m_cbMultiCast->Show();
1488 } else
1489 m_cbMultiCast->Hide();
1490}
1491
1492void ConnectionEditDialog::SetDefaultConnectionParams(void) {
1493 if (m_comboPort && !m_comboPort->IsListEmpty()) {
1494 m_comboPort->Select(0);
1495 m_comboPort->SetValue(wxEmptyString); // These two broke it
1496 }
1497 m_cbCheckCRC->SetValue(TRUE);
1498 m_cbGarminHost->SetValue(FALSE);
1499 m_cbInput->SetValue(TRUE);
1500 m_cbOutput->SetValue(FALSE);
1501 m_rbIAccept->SetValue(TRUE);
1502 m_rbOAccept->SetValue(TRUE);
1503 m_tcInputStc->SetValue(wxEmptyString);
1504 m_tcOutputStc->SetValue(wxEmptyString);
1505 m_choiceBaudRate->Select(m_choiceBaudRate->FindString("4800"));
1506 // m_choiceSerialProtocol->Select( cp->Protocol ); // TODO
1507
1508 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1509
1510 m_tNetComment->SetValue(wxEmptyString);
1511 m_tSerialComment->SetValue(wxEmptyString);
1512 m_tAuthToken->SetValue(wxEmptyString);
1513
1514 bool bserial = TRUE;
1515#ifdef __WXGTK__
1516 bserial = FALSE;
1517#endif
1518
1519#ifdef __WXOSX__
1520 bserial = FALSE;
1521#endif
1522
1523#ifdef __ANDROID__
1524 if (m_rbTypeInternalGPS) {
1525 m_rbTypeInternalGPS->SetValue(true);
1526 SetNMEAFormToGPS();
1527 } else {
1528 m_rbTypeNet->SetValue(true);
1529 SetNMEAFormToNet();
1530 }
1531
1532#else
1533 m_rbTypeSerial->SetValue(bserial);
1534 m_rbTypeNet->SetValue(!bserial);
1535 bserial ? SetNMEAFormToSerial() : SetNMEAFormToNet();
1536 m_rbTypeCAN->SetValue(FALSE);
1537#endif
1538
1539 m_connection_enabled = TRUE;
1540
1541 // Reset touch flag
1542 connectionsaved = false;
1543}
1544
1545void ConnectionEditDialog::LayoutDialog() {
1546 gSizerNetProps->Layout();
1547 gSizerSerProps->Layout();
1548 m_scrolledwin->Layout();
1549 m_scrolledwin->Fit();
1550 GetSizer()->Layout();
1551}
1552
1553void ConnectionEditDialog::UpdateSourceList(bool bResort) {
1554 for (auto* cp : TheConnectionParams()) {
1555 ConnectionParamsPanel* panel = cp->m_optionsPanel;
1556 if (panel) panel->Update(cp);
1557 }
1558
1559 m_scrollWinConnections->Layout();
1560}
1561
1562void ConnectionEditDialog::OnSelectDatasource(wxListEvent& event) {
1563 SetConnectionParams(TheConnectionParams()[event.GetData()]);
1564 m_buttonRemove->Enable();
1565 m_buttonRemove->Show();
1566 event.Skip();
1567}
1568
1569void ConnectionEditDialog::OnDiscoverButton(wxCommandEvent& event) {
1570#if 0 // FIXME (dave)
1571 wxString ip;
1572 int port;
1573 std::string serviceIdent =
1574 std::string("_signalk-ws._tcp.local."); // Works for node.js server
1575
1576 g_Platform->ShowBusySpinner();
1577
1578 if (SignalKDataStream::DiscoverSKServer(serviceIdent, ip, port,
1579 1)) // 1 second scan
1580 {
1581 m_tNetAddress->SetValue(ip);
1582 m_tNetPort->SetValue(wxString::Format(wxT("%i"), port));
1583 UpdateDiscoverStatus(_("Signal K server available."));
1584 } else {
1585 UpdateDiscoverStatus(_("Signal K server not found."));
1586 }
1587 g_Platform->HideBusySpinner();
1588#endif
1589 event.Skip();
1590}
1591
1592void ConnectionEditDialog::UpdateDiscoverStatus(wxString stat) {
1593 m_StaticTextSKServerStatus->SetLabel(stat);
1594}
1595
1596void ConnectionEditDialog::OnBtnIStcs(wxCommandEvent& event) {
1597 const ListType type = m_rbIAccept->GetValue() ? WHITELIST : BLACKLIST;
1598 const wxArrayString list = wxStringTokenize(m_tcInputStc->GetValue(), ",");
1599 SentenceListDlg dlg(m_parent, FILTER_INPUT, type, list);
1600
1601 if (dlg.ShowModal() == wxID_OK) m_tcInputStc->SetValue(dlg.GetSentences());
1602}
1603
1604void ConnectionEditDialog::OnBtnOStcs(wxCommandEvent& event) {
1605 const ListType type = m_rbOAccept->GetValue() ? WHITELIST : BLACKLIST;
1606 const wxArrayString list = wxStringTokenize(m_tcOutputStc->GetValue(), ",");
1607 SentenceListDlg dlg(m_parent, FILTER_OUTPUT, type, list);
1608
1609 if (dlg.ShowModal() == wxID_OK) m_tcOutputStc->SetValue(dlg.GetSentences());
1610}
1611
1612void ConnectionEditDialog::OnNetProtocolSelected(wxCommandEvent& event) {
1613 if (m_rbNetProtoGPSD->GetValue()) {
1614 if (IsDefaultPort(m_tNetPort->GetValue())) {
1615 m_tNetPort->SetValue(DEFAULT_GPSD_PORT);
1616 }
1617 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1618 } else if (m_rbNetProtoUDP->GetValue()) {
1619 if (IsDefaultPort(m_tNetPort->GetValue())) {
1620 m_tNetPort->SetValue(DEFAULT_UDP_PORT);
1621 }
1622 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1623 if (m_cbInput->GetValue() && !m_cbMultiCast->GetValue() &&
1624 m_rbNetProtoUDP->GetValue())
1625 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1626 else if (m_cbOutput->GetValue() && !m_cbMultiCast->GetValue())
1627 m_tNetPort->SetValue(DEFAULT_UDP_OUT_ADDRESS);
1628
1629 if (m_cbInput->GetValue() && m_cbOutput->GetValue())
1630 m_cbOutput->SetValue(false);
1631
1632 } else if (m_rbNetProtoSignalK->GetValue()) {
1633 if (IsDefaultPort(m_tNetPort->GetValue())) {
1634 m_tNetPort->SetValue(DEFAULT_SIGNALK_PORT);
1635 }
1636 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1637 } else if (m_rbNetProtoTCP->GetValue()) {
1638 if (IsDefaultPort(m_tNetPort->GetValue())) {
1639 m_tNetPort->SetValue(DEFAULT_TCP_PORT);
1640 }
1641 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1642 }
1643
1644 SetUDPNetAddressVisiblity();
1645 SetDSFormRWStates();
1646 LayoutDialog();
1647 OnConnValChange(event);
1648}
1649
1650void ConnectionEditDialog::OnRbAcceptInput(wxCommandEvent& event) {
1651 OnConnValChange(event);
1652}
1653void ConnectionEditDialog::OnRbIgnoreInput(wxCommandEvent& event) {
1654 OnConnValChange(event);
1655}
1656
1657void ConnectionEditDialog::OnRbOutput(wxCommandEvent& event) {
1658 OnConnValChange(event);
1659}
1660
1661void ConnectionEditDialog::OnCbInput(wxCommandEvent& event) {
1662 const bool checked = m_cbInput->IsChecked();
1663 ShowInFilter(checked);
1664 if (checked && m_rbNetProtoUDP->GetValue() && m_rbTypeNet->GetValue()) {
1665 m_cbOutput->SetValue(FALSE);
1666
1667 if (!m_cbMultiCast->GetValue()) m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1668 }
1669 SetDSFormRWStates();
1670 LayoutDialog();
1671 if (m_rbTypeNet->GetValue()) SetUDPNetAddressVisiblity();
1672 OnConnValChange(event);
1673}
1674
1675void ConnectionEditDialog::OnCbOutput(wxCommandEvent& event) {
1676 OnConnValChange(event);
1677 const bool checked = m_cbOutput->IsChecked();
1678 m_stPrecision->Enable(checked);
1679 m_choicePrecision->Enable(checked);
1680 ShowOutFilter(checked);
1681
1682 if (!m_cbMultiCast->IsChecked() && m_rbNetProtoUDP->GetValue()) {
1683 if (checked) {
1684 m_tNetAddress->SetValue(
1685 DEFAULT_UDP_OUT_ADDRESS); // IP address for output
1686 // Check for a UDP input connection on the same port
1687 NetworkProtocol proto = UDP;
1688 for (auto* cp : TheConnectionParams()) {
1689 if (cp->NetProtocol == proto &&
1690 cp->NetworkPort == wxAtoi(m_tNetPort->GetValue()) &&
1691 cp->IOSelect == DS_TYPE_INPUT) {
1692 // More: View the filter handler
1693 m_advanced = true;
1694 m_more->SetLabelMarkup(m_advanced ? LESS : MORE);
1695 SetNMEAFormForNetProtocol();
1696 LayoutDialog();
1697
1698 wxString mes;
1699 bool warn = false;
1700 if (cp->bEnabled) {
1701 mes =
1702 _("There is an enabled UDP input connection that uses the "
1703 "same data port.");
1704 mes << "\n"
1705 << _("Please apply a filter on both connections to avoid a "
1706 "feedback loop.");
1707 warn = true;
1708 } else {
1709 mes =
1710 _("There is a disabled UDP Input connection that uses the "
1711 "same Dataport.");
1712 mes << "\n"
1713 << _("If you enable that input please apply a filter on both "
1714 "connections to avoid a feedback loop.");
1715 }
1716 mes << "\n"
1717 << _("Or consider using a different data port for one of them");
1718 if (warn)
1719 OCPNMessageBox(this, mes, _("OpenCPN Warning"),
1720 wxOK | wxICON_EXCLAMATION, 60);
1721 else
1722 OCPNMessageBox(this, mes, _("OpenCPN info"),
1723 wxOK | wxICON_INFORMATION, 60);
1724 break;
1725 }
1726 }
1727 } else {
1728 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS); // IP address for input
1729 }
1730 }
1731
1732 if (checked && m_rbNetProtoUDP->GetValue()) {
1733 m_cbInput->SetValue(FALSE);
1734 }
1735
1736 if (m_rbTypeNet->GetValue()) SetUDPNetAddressVisiblity();
1737 SetDSFormRWStates();
1738 LayoutDialog();
1739}
1740
1741void ConnectionEditDialog::OnCbMultiCast(wxCommandEvent& event) {
1742 const bool checked = m_cbMultiCast->IsChecked();
1743 if (checked) {
1744 if (!IsAddressMultiCast(m_tNetAddress->GetValue())) {
1745 m_tNetAddress->SetValue("224.0.2.21");
1746 }
1747 } else if (m_cbOutput->IsChecked()) {
1748 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS); // IP address for output
1749 } else {
1750 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS); // IP address for input
1751 }
1752
1753 SetUDPNetAddressVisiblity();
1754 LayoutDialog();
1755}
1756
1757void ConnectionEditDialog::OnClickMore(wxMouseEvent& event) {
1758 // m_cbAdvanced->SetValue(!m_cbAdvanced->IsChecked());
1759 m_advanced = !m_advanced;
1760 m_more->SetLabelMarkup(m_advanced ? LESS : MORE);
1761 if (m_rbTypeNet->GetValue())
1762 SetNMEAFormForNetProtocol();
1763 else
1764 SetNMEAFormForSerialProtocol();
1765 LayoutDialog();
1766}
1767
1768void ConnectionEditDialog::OnCbAdvanced(wxCommandEvent& event) {
1769 if (m_rbTypeNet->GetValue())
1770 SetNMEAFormForNetProtocol();
1771 else
1772 SetNMEAFormForSerialProtocol();
1773 LayoutDialog();
1774}
1775
1776void ConnectionEditDialog::OnShowGpsWindowCheckboxClick(wxCommandEvent& event) {
1777 // if (!m_cbNMEADebug->GetValue()) {
1778 // NMEALogWindow::GetInstance().DestroyWindow();
1779 // } else {
1780 // NMEALogWindow::GetInstance().Create((wxWindow*)(m_parent->GetParent()),
1781 // 35);
1782 //
1783 // // Try to ensure that the log window is at least a little bit visible
1784 // wxRect logRect(NMEALogWindow::GetInstance().GetPosX(),
1785 // NMEALogWindow::GetInstance().GetPosY(),
1786 // NMEALogWindow::GetInstance().GetSizeW(),
1787 // NMEALogWindow::GetInstance().GetSizeH());
1788 // FIXME (leamas)
1789
1790#if 0
1791 if (m_container->GetRect().Contains(logRect)) {
1792 NMEALogWindow::Get().SetPos(
1793 m_container->GetRect().x / 2,
1794 (m_container->GetRect().y +
1795 (m_container->GetRect().height - logRect.height) / 2));
1796 NMEALogWindow::Get().Move();
1797 }
1798#endif
1799 m_parent->Raise();
1800 // }
1801}
1802void ConnectionEditDialog::SetNMEAFormForSerialProtocol() {
1803 bool n0183ctlenabled = (DataProtocol)m_choiceSerialProtocol->GetSelection() ==
1804 DataProtocol::PROTO_NMEA0183;
1805 bool advanced = m_advanced;
1806 ShowNMEACommon(n0183ctlenabled && advanced);
1807 m_cbGarminHost->Show(n0183ctlenabled && advanced);
1808
1809 SetDSFormRWStates();
1810 LayoutDialog();
1811}
1812
1813void ConnectionEditDialog::SetNMEAFormForNetProtocol() {
1814 bool n0183ctlenabled =
1815 (DataProtocol)m_choiceNetDataProtocol->GetSelection() ==
1816 DataProtocol::PROTO_NMEA0183;
1817 bool advanced = m_advanced;
1818 ShowNMEACommon(n0183ctlenabled && advanced);
1819 m_cbGarminHost->Show(n0183ctlenabled && advanced);
1820
1821 SetDSFormRWStates();
1822
1823 LayoutDialog();
1824}
1825
1826void ConnectionEditDialog::OnProtocolChoice(wxCommandEvent& event) {
1827 if (m_rbTypeNet->GetValue())
1828 SetNMEAFormForNetProtocol();
1829 else
1830 SetNMEAFormForSerialProtocol();
1831
1832 OnConnValChange(event);
1833}
1834
1835void ConnectionEditDialog::ApplySettings() {
1836#if 0
1837 g_bfilter_cogsog = m_cbFilterSogCog->GetValue();
1838
1839 long filter_val = 1;
1840 m_tFilterSec->GetValue().ToLong(&filter_val);
1841 g_COGFilterSec =
1842 wxMin(static_cast<int>(filter_val),
1843 60 /*MAX_COGSOG_FILTER_SECONDS*/); // FIXME (dave) should be
1844 g_COGFilterSec = wxMax(g_COGFilterSec, 1);
1845 g_SOGFilterSec = g_COGFilterSec;
1846
1847 g_bMagneticAPB = m_cbAPBMagnetic->GetValue();
1848 g_NMEAAPBPrecision = m_choicePrecision->GetCurrentSelection();
1849
1850 // NMEA Source
1851 // If the stream selected exists, capture some of its existing parameters
1852 // to facility identification and allow stop and restart of the stream
1853 wxString lastAddr;
1854 int lastPort = 0;
1855 NetworkProtocol lastNetProtocol = PROTO_UNDEFINED;
1856 DataProtocol lastDataProtocol = PROTO_NMEA0183;
1857
1858 if (mSelectedConnection) {
1859 ConnectionParams* cpo = mSelectedConnection;
1860 lastAddr = cpo->NetworkAddress;
1861 lastPort = cpo->NetworkPort;
1862 lastNetProtocol = cpo->NetProtocol;
1863 lastDataProtocol = cpo->Protocol;
1864 }
1865
1866 if (!connectionsaved) {
1867 size_t nCurrentPanelCount = TheConnectionParams()->GetCount();
1868 ConnectionParams* cp = NULL;
1869 int old_priority = -1;
1870 {
1871 if (mSelectedConnection) {
1872 cp = mSelectedConnection;
1873 old_priority = cp->Priority;
1874 UpdateConnectionParamsFromControls(cp);
1875 cp->b_IsSetup = false;
1876 // cp->bEnabled = false;
1877 // if (cp->m_optionsPanel)
1878 // cp->m_optionsPanel->SetEnableCheckbox(false);
1879
1880 // delete TheConnectionParams()->Item(itemIndex)->m_optionsPanel;
1881 // old_priority = TheConnectionParams()->Item(itemIndex)->Priority;
1882 // TheConnectionParams()->RemoveAt(itemIndex);
1883 // TheConnectionParams()->Insert(cp, itemIndex);
1884 // mSelectedConnection = cp;
1885 // cp->m_optionsPanel->SetSelected( true );
1886 } else {
1887 cp = CreateConnectionParamsFromSelectedItem();
1888 if (cp) TheConnectionParams()->Add(cp);
1889 }
1890
1891 // Record the previous parameters, if any
1892 if (cp) {
1893 cp->LastNetProtocol = lastNetProtocol;
1894 cp->LastNetworkAddress = lastAddr;
1895 cp->LastNetworkPort = lastPort;
1896 cp->LastDataProtocol = lastDataProtocol;
1897 }
1898
1899 if (TheConnectionParams()->GetCount() != nCurrentPanelCount)
1900 FillSourceList();
1901 else if (old_priority >= 0) {
1902 if (old_priority != cp->Priority) // need resort
1903 UpdateSourceList(true);
1904 else
1905 UpdateSourceList(false);
1906 }
1907
1908 connectionsaved = TRUE;
1909 }
1910 // else {
1911 // ::wxEndBusyCursor();
1912 // if (m_bNMEAParams_shown) event.SetInt(wxID_STOP);
1913 // }
1914
1915 SetSelectedConnectionPanel(nullptr);
1916 }
1917
1918 // Recreate datastreams that are new, or have been edited
1919 for (size_t i = 0; i < TheConnectionParams()->Count(); i++) {
1920 ConnectionParams* cp = TheConnectionParams()->Item(i);
1921
1922 if (cp->b_IsSetup) continue;
1923
1924 // Connection is new, or edited, or disabled
1925
1926 // Terminate and remove any existing driver, if present in registry
1927 StopAndRemoveCommDriver(cp->GetStrippedDSPort(), cp->GetCommProtocol());
1928
1929 // Stop and remove "previous" port, in case other params have changed.
1930 StopAndRemoveCommDriver(cp->GetLastDSPort(), cp->GetLastCommProtocol());
1931
1932 // Internal BlueTooth driver stacks commonly need a time delay to purge
1933 // their buffers, etc. before restating with new parameters...
1934 if (cp->Type == INTERNAL_BT) wxSleep(1);
1935
1936 // Connection has been disabled
1937 if (!cp->bEnabled) continue;
1938
1939 // Make any new or re-enabled drivers
1940 MakeCommDriver(cp);
1941 cp->b_IsSetup = TRUE;
1942 }
1943
1944 g_bGarminHostUpload = m_cbGarminUploadHost->GetValue();
1945 g_GPS_Ident =
1946 m_cbFurunoGP3X->GetValue() ? "FurunoGP3X" : "Generic";
1947#endif
1948}
1949
1951ConnectionEditDialog::CreateConnectionParamsFromSelectedItem() {
1952#if 0
1953 // FIXME (dave) How could this happen?
1954 // if (!m_bNMEAParams_shown) return NULL;
1955
1956 // Special encoding for deleted connection
1957 if (m_rbTypeSerial->GetValue() && m_comboPort->GetValue() == "Deleted")
1958 return NULL;
1959
1960 // We check some values here for consistency.
1961 // If necessary, set defaults so user will see some result, however wrong...
1962
1963 // DataStreams should be Input, Output, or Both
1964 if (!(m_cbInput->GetValue() || m_cbOutput->GetValue())) {
1965 m_cbInput->SetValue(true);
1966 }
1967
1968 if (m_rbTypeSerial->GetValue() && m_comboPort->GetValue() == wxEmptyString) {
1969 m_comboPort->Select(0);
1970 }
1971 // TCP, GPSD and UDP require port field to be set.
1972 // TCP clients, GPSD and UDP output sockets require an address
1973 else if (m_rbTypeNet->GetValue()) {
1974 if (wxAtoi(m_tNetPort->GetValue()) == 0) {
1975 m_tNetPort->SetValue("10110"); // reset to default
1976 }
1977 if (m_tNetAddress->GetValue() == wxEmptyString) {
1978 m_tNetAddress->SetValue("0.0.0.0");
1979 }
1980 } else if (m_rbTypeCAN->GetValue()) {
1981 }
1982
1983 ConnectionParams* pConnectionParams = new ConnectionParams();
1984
1985 UpdateConnectionParamsFromSelectedItem(pConnectionParams);
1986
1988 m_scrollWinConnections, wxID_ANY, wxDefaultPosition, wxDefaultSize,
1989 pConnectionParams, this);
1990 pPanel->SetSelected(false);
1991 boxSizerConnections->Add(pPanel, 0, wxEXPAND | wxALL, 0);
1992 pConnectionParams->m_optionsPanel = pPanel;
1993
1994 return pConnectionParams;
1995#endif
1996 return NULL;
1997}
1998
1999ConnectionParams* ConnectionEditDialog::GetParamsFromControls() {
2000 ConnectionParams* pConnectionParams = new ConnectionParams();
2001 UpdateConnectionParamsFromControls(pConnectionParams);
2002 return pConnectionParams;
2003}
2004
2005ConnectionParams* ConnectionEditDialog::UpdateConnectionParamsFromControls(
2006 ConnectionParams* pConnectionParams) {
2007 pConnectionParams->Valid = TRUE;
2008 if (m_rbTypeSerial->GetValue())
2009 pConnectionParams->Type = SERIAL;
2010 else if (m_rbTypeNet->GetValue())
2011 pConnectionParams->Type = NETWORK;
2012 else if (m_rbTypeInternalGPS && m_rbTypeInternalGPS->GetValue())
2013 pConnectionParams->Type = INTERNAL_GPS;
2014 else if (m_rbTypeInternalBT && m_rbTypeInternalBT->GetValue())
2015 pConnectionParams->Type = INTERNAL_BT;
2016 else if (m_rbTypeCAN && m_rbTypeCAN->GetValue())
2017 pConnectionParams->Type = SOCKETCAN;
2018
2019 if (m_rbTypeNet->GetValue()) {
2020 // Save the existing addr/port to allow closing of existing port
2021 pConnectionParams->LastNetworkAddress = pConnectionParams->NetworkAddress;
2022 pConnectionParams->LastNetworkPort = pConnectionParams->NetworkPort;
2023 pConnectionParams->LastNetProtocol = pConnectionParams->NetProtocol;
2024 pConnectionParams->LastDataProtocol = pConnectionParams->Protocol;
2025
2026 pConnectionParams->NetworkAddress =
2027 m_tNetAddress->GetValue().Trim(false).Trim(true);
2028 pConnectionParams->NetworkPort =
2029 wxAtoi(m_tNetPort->GetValue().Trim(false).Trim(true));
2030 if (m_rbNetProtoTCP->GetValue()) {
2031 pConnectionParams->NetProtocol = TCP;
2032 pConnectionParams->Protocol =
2033 (DataProtocol)m_choiceNetDataProtocol->GetSelection();
2034 } else if (m_rbNetProtoUDP->GetValue()) {
2035 pConnectionParams->NetProtocol = UDP;
2036 pConnectionParams->Protocol =
2037 (DataProtocol)m_choiceNetDataProtocol->GetSelection();
2038 } else if (m_rbNetProtoGPSD->GetValue())
2039 pConnectionParams->NetProtocol = GPSD;
2040 else if (m_rbNetProtoSignalK->GetValue())
2041 pConnectionParams->NetProtocol = SIGNALK;
2042 else
2043 pConnectionParams->NetProtocol = PROTO_UNDEFINED;
2044 }
2045
2046 if (m_rbTypeSerial->GetValue())
2047 pConnectionParams->Protocol =
2048 (DataProtocol)m_choiceSerialProtocol->GetSelection();
2049 else if (m_rbTypeNet->GetValue())
2050 pConnectionParams->Protocol =
2051 (DataProtocol)m_choiceNetDataProtocol->GetSelection();
2052
2053 pConnectionParams->Baudrate = wxAtoi(m_choiceBaudRate->GetStringSelection());
2054 pConnectionParams->ChecksumCheck = m_cbCheckCRC->GetValue();
2055 pConnectionParams->AutoSKDiscover = m_cbCheckSKDiscover->GetValue();
2056 pConnectionParams->Garmin = m_cbGarminHost->GetValue();
2057 pConnectionParams->InputSentenceList =
2058 wxStringTokenize(m_tcInputStc->GetValue(), ",");
2059 if (m_rbIAccept->GetValue())
2060 pConnectionParams->InputSentenceListType = WHITELIST;
2061 else
2062 pConnectionParams->InputSentenceListType = BLACKLIST;
2063 if (m_cbInput->GetValue()) {
2064 if (m_cbOutput->GetValue()) {
2065 pConnectionParams->IOSelect = DS_TYPE_INPUT_OUTPUT;
2066 } else {
2067 pConnectionParams->IOSelect = DS_TYPE_INPUT;
2068 }
2069 } else
2070 pConnectionParams->IOSelect = DS_TYPE_OUTPUT;
2071
2072 pConnectionParams->OutputSentenceList =
2073 wxStringTokenize(m_tcOutputStc->GetValue(), ",");
2074 if (m_rbOAccept->GetValue())
2075 pConnectionParams->OutputSentenceListType = WHITELIST;
2076 else
2077 pConnectionParams->OutputSentenceListType = BLACKLIST;
2078 pConnectionParams->Port = m_comboPort->GetValue().BeforeFirst(' ');
2079#if defined(__linux__) && !defined(__ANDROID__)
2080 if (pConnectionParams->Type == SERIAL)
2081 CheckSerialAccess(m_parent, pConnectionParams->Port.ToStdString());
2082#endif
2083
2084 if (m_rbTypeCAN && m_rbTypeCAN->GetValue())
2085 pConnectionParams->Protocol = PROTO_NMEA2000;
2086
2087 pConnectionParams->bEnabled = m_connection_enabled;
2088 pConnectionParams->b_IsSetup = FALSE;
2089
2090 if (pConnectionParams->Type == INTERNAL_GPS) {
2091 pConnectionParams->NetworkAddress = "";
2092 pConnectionParams->NetworkPort = 0;
2093 pConnectionParams->NetProtocol = PROTO_UNDEFINED;
2094 pConnectionParams->Baudrate = 0;
2095 }
2096
2097 if (pConnectionParams->Type == INTERNAL_BT) {
2098 wxString parms = m_choiceBTDataSources->GetStringSelection();
2099 wxStringTokenizer tkz(parms, ";");
2100 wxString name = tkz.GetNextToken();
2101 wxString mac = tkz.GetNextToken();
2102
2103 pConnectionParams->NetworkAddress = name;
2104 pConnectionParams->Port = mac;
2105 pConnectionParams->NetworkPort = 0;
2106 pConnectionParams->NetProtocol = PROTO_UNDEFINED;
2107 pConnectionParams->Baudrate = 0;
2108 // pConnectionParams->SetAuxParameterStr(m_choiceBTDataSources->GetStringSelection());
2109 }
2110
2111 if (pConnectionParams->Type == SOCKETCAN) {
2112 pConnectionParams->NetworkAddress = "";
2113 pConnectionParams->NetworkPort = 0;
2114 pConnectionParams->NetProtocol = PROTO_UNDEFINED;
2115 pConnectionParams->Baudrate = 0;
2116 pConnectionParams->socketCAN_port =
2117 m_choiceCANSource->GetString(m_choiceCANSource->GetSelection());
2118 }
2119
2120 if (pConnectionParams->Type == SERIAL) {
2121 pConnectionParams->UserComment = m_tSerialComment->GetValue();
2122 } else if (pConnectionParams->Type == NETWORK) {
2123 pConnectionParams->UserComment = m_tNetComment->GetValue();
2124 }
2125 pConnectionParams->AuthToken = m_tAuthToken->GetValue();
2126
2127 return pConnectionParams;
2128}
2129
2130void ConnectionEditDialog::OnPriorityDialog(wxCommandEvent& event) {
2131 PriorityDlg* pdlg = new PriorityDlg(m_parent);
2132 pdlg->ShowModal();
2133 delete pdlg;
2134}
2135void ConnectionEditDialog::ConnectControls() {
2136 // Connect controls
2137 m_rbTypeSerial->Connect(
2138 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2139 wxCommandEventHandler(ConnectionEditDialog::OnTypeSerialSelected), NULL,
2140 this);
2141 m_rbTypeNet->Connect(
2142 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2143 wxCommandEventHandler(ConnectionEditDialog::OnTypeNetSelected), NULL,
2144 this);
2145
2146 m_rbTypeCAN->Connect(
2147 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2148 wxCommandEventHandler(ConnectionEditDialog::OnTypeCANSelected), NULL,
2149 this);
2150
2151 if (m_rbTypeInternalGPS)
2152 m_rbTypeInternalGPS->Connect(
2153 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2154 wxCommandEventHandler(ConnectionEditDialog::OnTypeGPSSelected), NULL,
2155 this);
2156 if (m_rbTypeInternalBT)
2157 m_rbTypeInternalBT->Connect(
2158 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2159 wxCommandEventHandler(ConnectionEditDialog::OnTypeBTSelected), NULL,
2160 this);
2161
2162 // Network connection
2163 m_rbNetProtoTCP->Connect(
2164 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2165 wxCommandEventHandler(ConnectionEditDialog::OnNetProtocolSelected), NULL,
2166 this);
2167 m_rbNetProtoUDP->Connect(
2168 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2169 wxCommandEventHandler(ConnectionEditDialog::OnNetProtocolSelected), NULL,
2170 this);
2171 m_rbNetProtoGPSD->Connect(
2172 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2173 wxCommandEventHandler(ConnectionEditDialog::OnNetProtocolSelected), NULL,
2174 this);
2175 m_rbNetProtoSignalK->Connect(
2176 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2177 wxCommandEventHandler(ConnectionEditDialog::OnNetProtocolSelected), NULL,
2178 this);
2179 m_choiceNetDataProtocol->Connect(
2180 wxEVT_COMMAND_CHOICE_SELECTED,
2181 wxCommandEventHandler(ConnectionEditDialog::OnProtocolChoice), NULL,
2182 this);
2183 m_choiceSerialProtocol->Connect(
2184 wxEVT_COMMAND_CHOICE_SELECTED,
2185 wxCommandEventHandler(ConnectionEditDialog::OnProtocolChoice), NULL,
2186 this);
2187 m_cbMultiCast->Connect(
2188 wxEVT_COMMAND_CHECKBOX_CLICKED,
2189 wxCommandEventHandler(ConnectionEditDialog::OnCbMultiCast), NULL, this);
2190 // m_cbAdvanced->Connect(
2191 // wxEVT_COMMAND_CHECKBOX_CLICKED,
2192 // wxCommandEventHandler(ConnectionEditDialog::OnCbAdvanced), NULL, this);
2193 m_more->Bind(wxEVT_LEFT_DOWN, &ConnectionEditDialog::OnClickMore, this);
2194
2195 // input/output control
2196 m_cbInput->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
2197 wxCommandEventHandler(ConnectionEditDialog::OnCbInput),
2198 NULL, this);
2199 m_cbOutput->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
2200 wxCommandEventHandler(ConnectionEditDialog::OnCbOutput),
2201 NULL, this);
2202
2203 // Input filtering
2204 // m_rbIAccept->Connect(
2205 // wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2206 // wxCommandEventHandler(ConnectionEditDialog::OnRbAcceptInput), NULL,
2207 // this);
2208 // m_rbIIgnore->Connect(
2209 // wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2210 // wxCommandEventHandler(ConnectionEditDialog::OnRbIgnoreInput), NULL,
2211 // this);
2212 // m_tcInputStc->Connect(
2213 // wxEVT_COMMAND_TEXT_UPDATED,
2214 // wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL,
2215 // this);
2216 m_btnInputStcList->Connect(
2217 wxEVT_COMMAND_BUTTON_CLICKED,
2218 wxCommandEventHandler(ConnectionEditDialog::OnBtnIStcs), NULL, this);
2219
2220 // output filtering
2221 m_btnOutputStcList->Connect(
2222 wxEVT_COMMAND_BUTTON_CLICKED,
2223 wxCommandEventHandler(ConnectionEditDialog::OnBtnOStcs), NULL, this);
2224
2225#if 0
2226 m_tNetAddress->Connect(
2227 wxEVT_COMMAND_TEXT_UPDATED,
2228 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2229 m_tNetPort->Connect(wxEVT_COMMAND_TEXT_UPDATED,
2230 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange),
2231 NULL, this);
2232 m_comboPort->Connect(
2233 wxEVT_COMMAND_COMBOBOX_SELECTED,
2234 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2235 m_comboPort->Connect(
2236 wxEVT_COMMAND_TEXT_UPDATED,
2237 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2238 m_choiceBaudRate->Connect(
2239 wxEVT_COMMAND_CHOICE_SELECTED,
2240 wxCommandEventHandler(ConnectionEditDialog::OnBaudrateChoice), NULL, this);
2241 m_choicePriority->Connect(
2242 wxEVT_COMMAND_CHOICE_SELECTED,
2243 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2244 m_choiceCANSource->Connect(
2245 wxEVT_COMMAND_CHOICE_SELECTED,
2246 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2247 m_cbCheckCRC->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
2248 wxCommandEventHandler(ConnectionEditDialog::OnCrcCheck),
2249 NULL, this);
2250 m_cbGarminHost->Connect(
2251 wxEVT_COMMAND_CHECKBOX_CLICKED,
2252 wxCommandEventHandler(ConnectionEditDialog::OnUploadFormatChange), NULL,
2253 this);
2254 m_cbGarminUploadHost->Connect(
2255 wxEVT_COMMAND_CHECKBOX_CLICKED,
2256 wxCommandEventHandler(ConnectionEditDialog::OnUploadFormatChange), NULL,
2257 this);
2258 m_cbFurunoGP3X->Connect(
2259 wxEVT_COMMAND_CHECKBOX_CLICKED,
2260 wxCommandEventHandler(ConnectionEditDialog::OnUploadFormatChange), NULL,
2261 this);
2262 m_cbCheckSKDiscover->Connect(
2263 wxEVT_COMMAND_CHECKBOX_CLICKED,
2264 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2265 m_ButtonSKDiscover->Connect(
2266 wxEVT_COMMAND_BUTTON_CLICKED,
2267 wxCommandEventHandler(ConnectionEditDialog::OnDiscoverButton), NULL, this);
2268
2269 m_rbOAccept->Connect(wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2270 wxCommandEventHandler(ConnectionEditDialog::OnRbOutput),
2271 NULL, this);
2272 m_rbOIgnore->Connect(wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2273 wxCommandEventHandler(ConnectionEditDialog::OnRbOutput),
2274 NULL, this);
2275 m_tcOutputStc->Connect(
2276 wxEVT_COMMAND_TEXT_UPDATED,
2277 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2278 m_cbCheckCRC->Connect(
2279 wxEVT_COMMAND_CHECKBOX_CLICKED,
2280 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2281
2282 m_cbNMEADebug->Connect(
2283 wxEVT_COMMAND_CHECKBOX_CLICKED,
2284 wxCommandEventHandler(ConnectionEditDialog::OnShowGpsWindowCheckboxClick),
2285 NULL, this);
2286 m_cbFilterSogCog->Connect(
2287 wxEVT_COMMAND_CHECKBOX_CLICKED,
2288 wxCommandEventHandler(ConnectionEditDialog::OnValChange), NULL, this);
2289 m_tFilterSec->Connect(wxEVT_COMMAND_TEXT_UPDATED,
2290 wxCommandEventHandler(ConnectionEditDialog::OnValChange),
2291 NULL, this);
2292 m_cbAPBMagnetic->Connect(
2293 wxEVT_COMMAND_CHECKBOX_CLICKED,
2294 wxCommandEventHandler(ConnectionEditDialog::OnValChange), NULL, this);
2295
2296 m_ButtonPriorityDialog->Connect(
2297 wxEVT_COMMAND_BUTTON_CLICKED,
2298 wxCommandEventHandler(ConnectionEditDialog::OnPriorityDialog), NULL, this);
2299
2300 m_tNetComment->Connect(
2301 wxEVT_COMMAND_TEXT_UPDATED,
2302 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2303 m_tSerialComment->Connect(
2304 wxEVT_COMMAND_TEXT_UPDATED,
2305 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2306 m_tAuthToken->Connect(
2307 wxEVT_COMMAND_TEXT_UPDATED,
2308 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2309
2310 if (m_buttonScanBT)
2311 m_buttonScanBT->Connect(
2312 wxEVT_COMMAND_BUTTON_CLICKED,
2313 wxCommandEventHandler(ConnectionEditDialog::OnScanBTClick), NULL, this);
2314#endif
2315}
2316
2317bool ConnectionEditDialog::IsAddressMultiCast(wxString ip) {
2318 wxArrayString bytes = wxSplit(ip, '.');
2319 if (bytes.size() != 4) {
2320 return false;
2321 }
2322 unsigned long ipNum = (wxAtoi(bytes[0]) << 24) + (wxAtoi(bytes[1]) << 16) +
2323 (wxAtoi(bytes[2]) << 8) + wxAtoi(bytes[3]);
2324 unsigned long multicastStart = (224 << 24);
2325 unsigned long multicastEnd = (239 << 24) + (255 << 16) + (255 << 8) + 255;
2326 return ipNum >= multicastStart && ipNum <= multicastEnd;
2327}
2328
2329bool ConnectionEditDialog::IsDefaultPort(wxString address) {
2330 return (address == DEFAULT_TCP_PORT) || (address == DEFAULT_UDP_PORT) ||
2331 (address == DEFAULT_SIGNALK_PORT) || (address == DEFAULT_GPSD_PORT);
2332}
2333
2334bool ConnectionEditDialog::IsAddressBroadcast(wxString ip) {
2335 wxArrayString bytes = wxSplit(ip, '.');
2336 if (bytes.size() != 4) {
2337 std::cerr << "Invalid IP format." << std::endl;
2338 return false;
2339 }
2340 return wxAtoi(bytes[3]) == 255;
2341}
2342
2343SentenceListDlg::SentenceListDlg(wxWindow* parent, FilterDirection dir,
2344 ListType type, const wxArrayString& list)
2345 : wxDialog(parent, wxID_ANY, _("Sentence Filter"), wxDefaultPosition,
2346 wxSize(280, 420)),
2347 m_type(type),
2348 m_dir(dir),
2349 m_sentences(NMEA0183().GetRecognizedArray()) {
2350 m_sentences.Sort();
2351 wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
2352 wxBoxSizer* secondSizer = new wxBoxSizer(wxHORIZONTAL);
2353 wxStaticBox* pclbBox = new wxStaticBox(this, wxID_ANY, GetBoxLabel());
2354 wxStaticBoxSizer* stcSizer = new wxStaticBoxSizer(pclbBox, wxVERTICAL);
2355 m_clbSentences = new wxCheckListBox(this, wxID_ANY, wxDefaultPosition,
2356 wxDefaultSize, m_sentences);
2357 wxBoxSizer* btnEntrySizer = new wxBoxSizer(wxVERTICAL);
2358 wxButton* btnCheckAll = new wxButton(this, wxID_ANY, _("Select All"));
2359 wxButton* btnClearAll = new wxButton(this, wxID_ANY, _("Clear All"));
2360 wxButton* btnAdd = new wxButton(this, wxID_ANY, _("Add"));
2361 m_btnDel = new wxButton(this, wxID_ANY, _("Delete"));
2362 m_btnDel->Disable();
2363 wxStdDialogButtonSizer* btnSizer = new wxStdDialogButtonSizer();
2364 wxButton* btnOK = new wxButton(this, wxID_OK);
2365 wxButton* btnCancel = new wxButton(this, wxID_CANCEL, _("Cancel"));
2366
2367 secondSizer->Add(stcSizer, 1, wxALL | wxEXPAND, 5);
2368 stcSizer->Add(m_clbSentences, 1, wxALL | wxEXPAND, 5);
2369 btnEntrySizer->Add(btnCheckAll, 0, wxALL, 5);
2370 btnEntrySizer->Add(btnClearAll, 0, wxALL, 5);
2371 btnEntrySizer->AddSpacer(1);
2372 btnEntrySizer->Add(btnAdd, 0, wxALL, 5);
2373 btnEntrySizer->Add(m_btnDel, 0, wxALL, 5);
2374 secondSizer->Add(btnEntrySizer, 0, wxALL | wxEXPAND, 5);
2375 mainSizer->Add(secondSizer, 1, wxEXPAND, 5);
2376 btnSizer->AddButton(btnOK);
2377 btnSizer->AddButton(btnCancel);
2378 btnSizer->Realize();
2379 mainSizer->Add(btnSizer, 0, wxALL | wxEXPAND, 5);
2380
2381 SetSizer(mainSizer);
2382 mainSizer->SetSizeHints(this);
2383 Centre();
2384
2385 // Connect Events
2386 btnAdd->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
2387 wxCommandEventHandler(SentenceListDlg::OnAddClick), NULL,
2388 this);
2389 m_btnDel->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
2390 wxCommandEventHandler(SentenceListDlg::OnDeleteClick), NULL,
2391 this);
2392 m_clbSentences->Connect(wxEVT_COMMAND_LISTBOX_SELECTED,
2393 wxCommandEventHandler(SentenceListDlg::OnCLBSelect),
2394 NULL, this);
2395 btnCheckAll->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
2396 wxCommandEventHandler(SentenceListDlg::OnCheckAllClick),
2397 NULL, this);
2398 btnClearAll->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
2399 wxCommandEventHandler(SentenceListDlg::OnClearAllClick),
2400 NULL, this);
2401
2402 Populate(list);
2403}
2404
2405wxString SentenceListDlg::GetBoxLabel(void) const {
2406 if (m_dir == FILTER_OUTPUT)
2407 return m_type == WHITELIST ? _("Transmit sentences") : _("Drop sentences");
2408 else
2409 return m_type == WHITELIST ? _("Accept only sentences")
2410 : _("Ignore sentences");
2411}
2412
2413void SentenceListDlg::Populate(const wxArrayString& list) {
2414 if (m_dir == FILTER_OUTPUT) {
2415 wxString s;
2416 m_sentences.Add(g_TalkerIdText + wxString("RMB"));
2417 m_sentences.Add(g_TalkerIdText + wxString("RMC"));
2418 m_sentences.Add(g_TalkerIdText + wxString("APB"));
2419 m_sentences.Add(g_TalkerIdText + wxString("XTE"));
2420 }
2421 m_sentences.Add("AIVDM");
2422 m_sentences.Add("AIVDO");
2423 m_sentences.Add("FRPOS");
2424 m_sentences.Add(g_TalkerIdText);
2425 m_sentences.Add("CD");
2426 m_sentences.Sort();
2427 m_clbSentences->Clear();
2428 m_clbSentences->InsertItems(m_sentences, 0);
2429
2430 wxArrayString new_strings;
2431
2432 if (list.Count() == 0) {
2433 for (size_t i = 0; i < m_clbSentences->GetCount(); ++i)
2434 m_clbSentences->Check(i, m_type == WHITELIST);
2435 } else {
2436 for (size_t i = 0; i < list.Count(); ++i) {
2437 int item = m_clbSentences->FindString(list[i]);
2438 if (item != wxNOT_FOUND)
2439 m_clbSentences->Check(item);
2440 else
2441 new_strings.Add(list[i]);
2442 }
2443 if (new_strings.GetCount()) {
2444 m_clbSentences->InsertItems(new_strings, m_clbSentences->GetCount());
2445 for (size_t i = 0; i < new_strings.GetCount(); ++i) {
2446 int item = m_clbSentences->FindString(new_strings[i]);
2447 if (item != wxNOT_FOUND) m_clbSentences->Check(item);
2448 }
2449 }
2450 }
2451}
2452
2453wxString SentenceListDlg::GetSentences(void) {
2454 wxArrayString retString;
2455 for (size_t i = 0; i < m_clbSentences->GetCount(); i++) {
2456 if (m_clbSentences->IsChecked(i))
2457 retString.Add(m_clbSentences->GetString(i));
2458 }
2459 return StringArrayToString(retString);
2460}
2461
2462void SentenceListDlg::OnCLBSelect(wxCommandEvent& e) {
2463 // Only activate the "Delete" button if the selection is not in the standard
2464 // list
2465 m_btnDel->Enable(m_sentences.Index(e.GetString()) == wxNOT_FOUND);
2466}
2467
2468void SentenceListDlg::OnAddClick(wxCommandEvent& event) {
2469#ifdef __ANDROID__
2470 androidDisableRotation();
2471#endif
2472
2473 wxTextEntryDialog textdlg(
2474 this,
2475 _("Enter the NMEA sentence (2, 3 or 5 characters)\n or a valid REGEX "
2476 "expression (6 characters or longer)"),
2477 _("Enter the NMEA sentence"));
2478
2479 textdlg.SetTextValidator(wxFILTER_ASCII);
2480 int result = textdlg.ShowModal();
2481
2482#ifdef __ANDROID__
2483 androidEnableRotation();
2484#endif
2485
2486 if (result == wxID_CANCEL) return;
2487 wxString stc = textdlg.GetValue();
2488
2489 if (stc.Length() == 2 || stc.Length() == 3 || stc.Length() == 5) {
2490 m_clbSentences->Append(stc);
2491 m_clbSentences->Check(m_clbSentences->FindString(stc));
2492 return;
2493 } else if (stc.Length() < 2) {
2494 OCPNMessageBox(
2495 this,
2496 _("An NMEA sentence is generally 3 characters long (like RMC, GGA etc.)\n \
2497 It can also have a two letter prefix identifying the source, or TALKER, of the message.\n \
2498 The whole sentences then looks like GPGGA or AITXT.\n \
2499 You may filter out all the sentences with certain TALKER prefix (like GP, AI etc.).\n \
2500 The filter also accepts Regular Expressions (REGEX) with 6 or more characters. \n\n"),
2501 _("OpenCPN Info"));
2502 return;
2503 }
2504
2505 else {
2506 // Verify that a longer text entry is a valid RegEx
2507 wxRegEx r(stc);
2508 if (r.IsValid()) {
2509 m_clbSentences->Append(stc);
2510 m_clbSentences->Check(m_clbSentences->FindString(stc));
2511 return;
2512 } else {
2513 OCPNMessageBox(this, _("REGEX syntax error: \n") + stc,
2514 _("OpenCPN Info"));
2515 return;
2516 }
2517 }
2518}
2519
2520void SentenceListDlg::OnDeleteClick(wxCommandEvent& event) {
2521 m_clbSentences->Delete(m_clbSentences->GetSelection());
2522}
2523
2524void SentenceListDlg::OnClearAllClick(wxCommandEvent& event) {
2525 for (size_t i = 0; i < m_clbSentences->GetCount(); i++)
2526 m_clbSentences->Check(i, FALSE);
2527}
2528
2529void SentenceListDlg::OnCheckAllClick(wxCommandEvent& event) {
2530 for (size_t i = 0; i < m_clbSentences->GetCount(); i++)
2531 m_clbSentences->Check(i, TRUE);
2532}
Panel for displaying and editing connection parameters.
Provides platform-specific support utilities for OpenCPN.
void Init(const KeyProvider &kp, std::function< void(ObservedEvt &ev)> action)
Initiate an object yet not listening.
Definition observable.h:255
Custom event class for OpenCPN's notification system.
Dialog and support code for editing a connection.
General purpose GUI support.
std::vector< std::string > split(const char *token_string, const std::string &delimiter)
Return vector of items in s separated by delimiter.
std::string trim(std::string s)
Strip possibly trailing and/or leading space characters in s.
PlugIn Object Definition/API.
Miscellaneous utilities, many of which string related.
Suspend/resume and new devices events exchange point.
bool CheckSerialAccess(wxWindow *parent, const std::string device)
Run checks and possible dialogs to ensure device is accessible.
Access checks for comm devices and dongle.