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