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