OpenCPN Partial API docs
Loading...
Searching...
No Matches
connection_edit.cpp
1/******************************************************************************
2 *
3 * Project: OpenCPN
4 * Purpose:
5 * Author: David Register
6 *
7 ***************************************************************************
8 * Copyright (C) 2022 by David S. Register *
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
24 ***************************************************************************
25 *
26 *
27 */
28
29#include <set>
30
31#include <wx/wxprec.h>
32
33#ifndef WX_PRECOMP
34#include <wx/wx.h>
35#endif // precompiled headers
36
37#include "config.h"
38
39#include <wx/tokenzr.h>
40#include <wx/regex.h>
41
42#if defined(__linux__) && !defined(__ANDROID__)
43#include <linux/can.h>
44#include <linux/can/raw.h>
45#include <net/if.h>
46#include <serial/serial.h>
47#include <sys/ioctl.h>
48#include <sys/socket.h>
49#include "dnet.h"
50#endif
51
52#ifdef __ANDROID__
53#include "androidUTIL.h"
54#include "qdebug.h"
55#endif
56
57#include "model/comm_drv_factory.h"
58#include "model/config_vars.h"
59#include "model/ocpn_utils.h"
60#include "model/ser_ports.h"
61#include "model/sys_events.h"
62
63#include "connection_edit.h"
64#include "conn_params_panel.h"
65#include "gui_lib.h"
66#include "nmea0183.h"
67#include "OCPNPlatform.h"
68#include "ocpn_plugin.h" // FIXME for GetOCPNScaledFont_PlugIn
69#include "options.h"
70#include "priority_gui.h"
71#include "udev_rule_mgr.h"
72
73extern OCPNPlatform* g_Platform;
74
75static wxString StringArrayToString(const wxArrayString& arr) {
76 wxString ret = wxEmptyString;
77 for (size_t i = 0; i < arr.Count(); i++) {
78 if (i > 0) ret.Append(",");
79 ret.Append(arr[i]);
80 }
81 return ret;
82}
83
84// Check available SocketCAN interfaces
85
86#if defined(__linux__) && !defined(__ANDROID__)
87static intf_t* intf;
88std::vector<std::string> can_if_candidates;
89static int print_intf(const struct intf_entry* entry, void* arg) {
90 std::string iface = entry->intf_name;
91 if (entry->intf_type == 1 && iface.find("can") != std::string::npos) {
92 can_if_candidates.push_back(entry->intf_name);
93 }
94 return 0;
95}
96#endif
97
98static wxArrayString GetAvailableSocketCANInterfaces() {
99 wxArrayString rv;
100
101#if defined(__linux__) && !defined(__ANDROID__)
102 struct intf_entry* entry;
103
104 can_if_candidates.clear();
105
106 if ((intf = intf_open()) == NULL) {
107 wxLogWarning("Error opening interface list");
108 }
109
110 if (intf_loop(intf, print_intf, NULL) < 0) {
111 wxLogWarning("Error looping over interface list");
112 }
113 intf_close(intf);
114
115 for (const auto& iface : can_if_candidates) {
116 int sock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
117 if (sock < 0) {
118 continue;
119 }
120
121 // Get the interface index
122 struct ifreq if_request;
123 strcpy(if_request.ifr_name, iface.c_str());
124 if (ioctl(sock, SIOCGIFINDEX, &if_request) < 0) {
125 continue;
126 }
127
128 // Check if interface is UP
129 struct sockaddr_can can_address;
130 can_address.can_family = AF_CAN;
131 can_address.can_ifindex = if_request.ifr_ifindex;
132 if (ioctl(sock, SIOCGIFFLAGS, &if_request) < 0) {
133 continue;
134 }
135 if (if_request.ifr_flags & IFF_UP) {
136 rv.Add(iface);
137 } else {
138 continue;
139 }
140 }
141#endif
142 return rv;
143}
144
145static void LoadSerialPorts(wxComboBox* box) {
147 class PortSorter {
148 private:
149 std::string GetKey(const std::string& s) const {
150 if (s.find("->") == std::string::npos) return s;
151 return ocpn::trim(ocpn::split(s, "->")[1]) + " link";
152 }
153
154 public:
155 bool operator()(const std::string& lhs, const std::string& rhs) const {
156 return GetKey(lhs) < GetKey(rhs);
157 }
158 } port_sorter;
159
160 std::set<std::string, PortSorter> sorted_ports(port_sorter);
161 std::unique_ptr<wxArrayString> ports(EnumerateSerialPorts());
162 for (size_t i = 0; i < ports->GetCount(); i++)
163 sorted_ports.insert((*ports)[i].ToStdString());
164
165 auto value = box->GetValue();
166 box->Clear();
167 for (auto& p : sorted_ports) box->Append(p);
168 if (!value.empty()) box->SetValue(value);
169}
170
171//------------------------------------------------------------------------------
172// ConnectionEditDialog Implementation
173//------------------------------------------------------------------------------
174
175// Define constructors
176ConnectionEditDialog::ConnectionEditDialog() {}
177
178ConnectionEditDialog::ConnectionEditDialog(
179 wxWindow* parent,
180 std::function<void(ConnectionParams* p, bool editing, bool ok_cancel)>
181 _on_edit_click)
182 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(-1, -1), 0,
183 "conn_edit"),
184 m_on_edit_click(_on_edit_click) {
185 m_parent = parent;
186
187 Init();
188}
189
190ConnectionEditDialog::~ConnectionEditDialog() {}
191
192void ConnectionEditDialog::SetInitialSettings(void) {
193 LoadSerialPorts(m_comboPort);
194}
195
196void ConnectionEditDialog::AddOKCancelButtons() {
197#ifndef ANDROID
198 if (!m_btnSizer) {
199 m_btnSizer = new wxStdDialogButtonSizer();
200 m_btnOK = new wxButton(this, wxID_OK);
201 m_btnCancel = new wxButton(this, wxID_CANCEL, _("Cancel"));
202 m_btnSizer->AddButton(m_btnOK);
203 m_btnSizer->AddButton(m_btnCancel);
204 m_btnSizer->Realize();
205 GetSizer()->Add(m_btnSizer, 0, wxALL | wxEXPAND, 5);
206 m_btnSizer->Show(true);
207 }
208#else
209 if (!m_btnSizerBox) {
210 m_btnSizerBox = new wxBoxSizer(wxHORIZONTAL);
211 m_btnOK = new wxButton(this, wxID_OK);
212 m_btnCancel = new wxButton(this, wxID_CANCEL, _("Cancel"));
213 m_btnSizerBox->AddSpacer(wxWindow::GetCharWidth());
214 m_btnSizerBox->Add(m_btnOK, 0, wxALL, 5);
215 m_btnSizerBox->Add(m_btnCancel, 0, wxALL, 5);
216 GetSizer()->Add(m_btnSizerBox, 0, wxALL | wxEXPAND, 5);
217 }
218#endif
219
220 m_btnOK->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
221 [&](wxCommandEvent& ev) { OnOKClick(); });
222 m_btnCancel->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
223 [&](wxCommandEvent& ev) { OnCancelClick(); });
224}
225
226void ConnectionEditDialog::OnOKClick() {
227 m_on_edit_click(m_cp_original, new_mode, true);
228}
229
230void ConnectionEditDialog::OnCancelClick() {
231 m_on_edit_click(nullptr, false, false);
232}
233
234void ConnectionEditDialog::Init() {
235 wxFont* qFont = GetOCPNScaledFont(_("Dialog"));
236 SetFont(*qFont);
237
238 m_btnSizer = nullptr;
239 m_btnSizerBox = nullptr;
240
241 // Setup some inital 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(TRUE);
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(void) {
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 m_stNetAddr->Show(visible);
1003 m_tNetAddress->Show(visible);
1004 m_stNetDataProtocol->Show(visible);
1005 m_stNetPort->Show(visible);
1006 m_choiceNetDataProtocol->Show(visible);
1007 m_tNetPort->Show(visible);
1008 m_stNetProto->Show(visible);
1009 m_rbNetProtoSignalK->Show(visible);
1010 m_rbNetProtoGPSD->Show(visible);
1011 m_rbNetProtoTCP->Show(visible);
1012 m_rbNetProtoUDP->Show(visible);
1013 m_stNetComment->Show(visible);
1014 m_tNetComment->Show(visible);
1015 m_stAuthToken->Show(visible);
1016 m_tAuthToken->Show(visible);
1017 m_cbGarminHost->Hide();
1018}
1019
1020void ConnectionEditDialog::ShowNMEASerial(bool visible) {
1021 bool advanced = m_advanced;
1022 m_stSerBaudrate->Show(visible);
1023 m_choiceBaudRate->Show(visible);
1024 m_stSerPort->Show(visible);
1025 m_comboPort->Show(visible);
1026 m_stSerProtocol->Show(visible);
1027 m_choiceSerialProtocol->Show(visible);
1028 m_cbGarminHost->Show(visible && advanced);
1029 m_stSerialComment->Show(visible);
1030 m_tSerialComment->Show(visible);
1031}
1032
1033void ConnectionEditDialog::ShowNMEAGPS(bool visible) {
1034 m_cbCheckSKDiscover->Hide();
1035 m_ButtonSKDiscover->Hide();
1036 m_stAuthToken->Hide();
1037 m_tAuthToken->Hide();
1038 m_cbOutput->Hide();
1039}
1040
1041void ConnectionEditDialog::ShowNMEACAN(bool visible) {
1042 m_stCANSource->Show(visible);
1043 m_choiceCANSource->Show(visible);
1044}
1045
1046void ConnectionEditDialog::ShowNMEABT(bool visible) {
1047 if (visible) {
1048 if (m_buttonScanBT) m_buttonScanBT->Show();
1049 if (m_stBTPairs) m_stBTPairs->Show();
1050 if (m_choiceBTDataSources) {
1051 if (m_choiceBTDataSources->GetCount() > 1)
1052 m_choiceBTDataSources->SetSelection(1);
1053 m_choiceBTDataSources->Show();
1054 }
1055 } else {
1056 if (m_buttonScanBT) m_buttonScanBT->Hide();
1057 if (m_stBTPairs) m_stBTPairs->Hide();
1058 if (m_choiceBTDataSources) m_choiceBTDataSources->Hide();
1059 }
1060 m_cbCheckSKDiscover->Hide();
1061 m_stAuthToken->Hide();
1062 m_tAuthToken->Hide();
1063 m_cbCheckSKDiscover->Hide(); // Provisional
1064 m_ButtonSKDiscover->Hide();
1065 m_tcOutputStc->Show(visible);
1066 m_btnOutputStcList->Show(visible);
1067 m_cbOutput->Show(visible);
1068}
1069
1070void ConnectionEditDialog::SetNMEAFormToSerial(void) {
1071 bool advanced = m_advanced;
1072 ShowNMEACommon(TRUE);
1073 ShowNMEANet(FALSE);
1074 ShowNMEAGPS(FALSE);
1075 ShowNMEABT(FALSE);
1076 ShowNMEASerial(TRUE);
1077 ShowNMEACAN(FALSE);
1078 SetDSFormRWStates();
1079 LayoutDialog();
1080}
1081
1082void ConnectionEditDialog::SetNMEAFormToNet(void) {
1083 bool advanced = m_advanced;
1084 ShowNMEACommon(TRUE);
1085 ShowNMEANet(TRUE);
1086 ShowNMEAGPS(FALSE);
1087 ShowNMEABT(FALSE);
1088 ShowNMEASerial(FALSE);
1089 ShowNMEACAN(FALSE);
1090 SetUDPNetAddressVisiblity();
1091 SetDSFormRWStates();
1092
1093 LayoutDialog();
1094}
1095
1096void ConnectionEditDialog::SetNMEAFormToCAN(void) {
1097 bool advanced = m_advanced;
1098 ShowNMEACommon(FALSE);
1099 ShowNMEANet(FALSE);
1100 ShowNMEAGPS(FALSE);
1101 ShowNMEABT(FALSE);
1102 ShowNMEASerial(FALSE);
1103 ShowNMEACAN(TRUE);
1104 sbSizerInFilter->Show(false);
1105 sbSizerOutFilter->Show(false);
1106 SetDSFormRWStates();
1107
1108 LayoutDialog();
1109}
1110
1111void ConnectionEditDialog::SetNMEAFormToGPS(void) {
1112 ShowNMEACommon(TRUE);
1113 ShowNMEANet(FALSE);
1114 ShowNMEAGPS(TRUE);
1115 ShowNMEABT(FALSE);
1116 ShowNMEASerial(FALSE);
1117 ShowNMEACAN(FALSE);
1118
1119 // m_container->FitInside();
1120 // Fit();
1121 SetDSFormRWStates();
1122 LayoutDialog();
1123}
1124
1125void ConnectionEditDialog::SetNMEAFormToBT(void) {
1126 m_rbNetProtoUDP->SetValue(true);
1127 ShowNMEACommon(TRUE);
1128 ShowNMEANet(FALSE);
1129 ShowNMEAGPS(FALSE);
1130 ShowNMEABT(TRUE);
1131 ShowNMEASerial(FALSE);
1132 ShowNMEACAN(FALSE);
1133
1134 // m_container->FitInside();
1135 // Fit();
1136 SetDSFormRWStates();
1137 LayoutDialog();
1138}
1139
1140void ConnectionEditDialog::ClearNMEAForm(void) {
1141 ShowNMEACommon(FALSE);
1142 ShowNMEANet(FALSE);
1143 ShowNMEAGPS(FALSE);
1144 ShowNMEABT(FALSE);
1145 ShowNMEASerial(FALSE);
1146 ShowNMEACAN(FALSE);
1147
1148 // m_container->FitInside();
1149 // Fit();
1150}
1151
1152void ConnectionEditDialog::SetDSFormOptionVizStates(void) {
1153 bool advanced = m_advanced;
1154 m_collapse_box->ShowItems(true);
1155 m_cbInput->Show();
1156 m_cbOutput->Show();
1157 m_stPrecision->Show(true);
1158 m_choicePrecision->Show(true);
1159
1160 ShowInFilter(advanced);
1161 ShowOutFilter(advanced);
1162 // Discovery hidden until it works.
1163 // m_cbCheckSKDiscover->Show();
1164 m_stAuthToken->Show(advanced);
1165 m_tAuthToken->Show(advanced);
1166 // m_ButtonSKDiscover->Show();
1167 m_StaticTextSKServerStatus->Show(advanced);
1168
1169 if (m_rbTypeSerial->GetValue()) {
1170 m_cbMultiCast->Hide();
1171 m_cbCheckSKDiscover->Hide();
1172 m_stAuthToken->Hide();
1173 m_tAuthToken->Hide();
1174 m_ButtonSKDiscover->Hide();
1175 m_StaticTextSKServerStatus->Hide();
1176 bool n0183ctlenabled =
1177 (DataProtocol)m_choiceSerialProtocol->GetSelection() ==
1178 DataProtocol::PROTO_NMEA0183;
1179 bool n2kctlenabled = (DataProtocol)m_choiceSerialProtocol->GetSelection() ==
1180 DataProtocol::PROTO_NMEA2000;
1181 if (!n0183ctlenabled) {
1182 if (n2kctlenabled) {
1183 m_cbInput->Show();
1184 m_cbOutput->Show();
1185 } else {
1186 m_cbInput->Hide();
1187 m_cbOutput->Hide();
1188 }
1189 ShowOutFilter(false);
1190 ShowInFilter(false);
1191 m_stPrecision->Hide();
1192 m_choicePrecision->Hide();
1193 m_stNetDataProtocol->Hide();
1194 m_choiceNetDataProtocol->Hide();
1195 } else {
1196 m_cbInput->Show();
1197 m_cbInput->Enable();
1198
1199 ShowInFilter(m_cbInput->IsChecked() && advanced);
1200 ShowOutFilter(m_cbOutput->IsChecked() && advanced);
1201
1202 m_stPrecision->Show(m_cbOutput->IsChecked() && advanced);
1203 m_choicePrecision->Show(m_cbOutput->IsChecked() && advanced);
1204
1205 m_cbGarminHost->Show(m_cbInput->IsChecked() && advanced);
1206 }
1207 }
1208
1209 if (m_rbTypeInternalGPS && m_rbTypeInternalGPS->GetValue()) {
1210 m_cbMultiCast->Hide();
1211 m_cbCheckSKDiscover->Hide();
1212 m_stAuthToken->Hide();
1213 m_tAuthToken->Hide();
1214 m_ButtonSKDiscover->Hide();
1215 m_StaticTextSKServerStatus->Hide();
1216 m_cbOutput->Hide();
1217 m_cbInput->Hide();
1218 ShowOutFilter(false);
1219 ShowInFilter(false);
1220 m_stPrecision->Hide();
1221 m_choicePrecision->Hide();
1222 m_cbGarminHost->Hide();
1223 m_collapse_box->ShowItems(false);
1224 }
1225
1226 if (m_rbTypeInternalBT && m_rbTypeInternalBT->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
1234 ShowInFilter(m_cbInput->IsChecked() && advanced);
1235 ShowOutFilter(m_cbOutput->IsChecked() && advanced);
1236
1237 m_stPrecision->Show(m_cbOutput->IsChecked() && advanced);
1238 m_choicePrecision->Show(m_cbOutput->IsChecked() && advanced);
1239 }
1240
1241 if (m_rbTypeCAN->GetValue()) {
1242 m_cbMultiCast->Hide();
1243 m_cbCheckSKDiscover->Hide();
1244 m_stAuthToken->Hide();
1245 m_tAuthToken->Hide();
1246 m_ButtonSKDiscover->Hide();
1247 m_StaticTextSKServerStatus->Hide();
1248 m_cbGarminHost->Hide();
1249 m_cbInput->Hide();
1250 m_cbOutput->Hide();
1251
1252 ShowInFilter(false);
1253 ShowOutFilter(false);
1254
1255 m_stPrecision->Hide();
1256 m_choicePrecision->Hide();
1257
1258 m_stNetDataProtocol->Hide();
1259 m_choiceNetDataProtocol->Hide();
1260 m_collapse_box->Show(false);
1261 }
1262
1263 if (m_rbTypeNet->GetValue()) {
1264 if (m_rbNetProtoGPSD->GetValue()) {
1265 m_cbMultiCast->Hide();
1266 m_cbCheckSKDiscover->Hide();
1267 m_cbInput->Hide();
1268 m_cbOutput->Hide();
1269 ShowInFilter(true);
1270 ShowOutFilter(false);
1271 m_stPrecision->Hide();
1272 m_choicePrecision->Hide();
1273 m_ButtonSKDiscover->Hide();
1274 m_StaticTextSKServerStatus->Hide();
1275 m_stAuthToken->Hide();
1276 m_tAuthToken->Hide();
1277 m_stNetDataProtocol->Hide();
1278 m_choiceNetDataProtocol->Hide();
1279 m_cbGarminHost->Hide();
1280 m_collapse_box->Show(false);
1281
1282 } else if (m_rbNetProtoSignalK->GetValue()) {
1283 m_cbMultiCast->Hide();
1284 m_cbInput->Hide();
1285 m_cbOutput->Hide();
1286 ShowInFilter(false);
1287 ShowOutFilter(false);
1288 m_stPrecision->Hide();
1289 m_choicePrecision->Hide();
1290 m_stNetDataProtocol->Hide();
1291 m_choiceNetDataProtocol->Hide();
1292 m_cbGarminHost->Hide();
1293
1294 } else { // tcp or udp
1295 m_stAuthToken->Hide();
1296 m_tAuthToken->Hide();
1297 m_cbCheckSKDiscover->Hide();
1298 m_ButtonSKDiscover->Hide();
1299 m_StaticTextSKServerStatus->Hide();
1300 m_stNetDataProtocol->Show();
1301 m_choiceNetDataProtocol->Show();
1302 m_cbGarminHost->Hide();
1303
1304 // if (m_rbNetProtoUDP->GetValue()) m_cbMultiCast->Show(advanced);
1305
1306 if ((DataProtocol)m_choiceNetDataProtocol->GetSelection() ==
1307 DataProtocol::PROTO_NMEA2000) {
1308 m_stPrecision->Hide();
1309 m_choicePrecision->Hide();
1310
1311 ShowInFilter(false);
1312 ShowOutFilter(false);
1313 if (m_rbNetProtoTCP->GetValue()) m_collapse_box->ShowItems(false);
1314 }
1315 if ((DataProtocol)m_choiceNetDataProtocol->GetSelection() ==
1316 DataProtocol::PROTO_NMEA0183) {
1317 m_stPrecision->Show(advanced);
1318 m_choicePrecision->Show(advanced);
1319 m_stPrecision->Enable(m_cbOutput->IsChecked() && advanced);
1320 m_choicePrecision->Enable(m_cbOutput->IsChecked() && advanced);
1321
1322 ShowInFilter(m_cbInput->IsChecked() && advanced);
1323 ShowOutFilter(m_cbOutput->IsChecked() && advanced);
1324 }
1325 }
1326 }
1327}
1328
1329void ConnectionEditDialog::SetDSFormRWStates(void) {
1330 if (m_rbTypeSerial->GetValue()) {
1331 m_cbInput->Enable(TRUE);
1332 m_cbOutput->Enable(TRUE);
1333 ShowInFilter();
1334 ShowOutFilter(m_cbOutput->IsChecked());
1335 } else if (m_rbNetProtoGPSD->GetValue()) {
1336 if (m_tNetPort->GetValue() == wxEmptyString)
1337 m_tNetPort->SetValue(DEFAULT_GPSD_PORT);
1338 m_cbInput->SetValue(TRUE);
1339 m_cbInput->Enable(FALSE);
1340 // m_cbOutput->SetValue(FALSE);
1341 m_cbOutput->Enable(FALSE);
1342 m_rbOAccept->Enable(FALSE);
1343 m_rbOIgnore->Enable(FALSE);
1344 m_btnOutputStcList->Enable(FALSE);
1345 } else if (m_rbNetProtoSignalK->GetValue()) {
1346 if (m_tNetPort->GetValue() == wxEmptyString)
1347 m_tNetPort->SetValue(DEFAULT_SIGNALK_PORT);
1348 m_cbInput->SetValue(TRUE);
1349 m_cbInput->Enable(FALSE);
1350 // m_cbOutput->SetValue(FALSE);
1351 m_cbOutput->Enable(FALSE);
1352 m_rbOAccept->Enable(FALSE);
1353 m_rbOIgnore->Enable(FALSE);
1354 UpdateDiscoverStatus(wxEmptyString);
1355 } else {
1356 if (m_tNetPort->GetValue() == wxEmptyString) {
1357 if (m_rbNetProtoTCP->GetValue()) {
1358 m_tNetPort->SetValue(DEFAULT_TCP_PORT);
1359 } else {
1360 m_tNetPort->SetValue(DEFAULT_UDP_PORT);
1361 }
1362 }
1363 m_cbInput->Enable(TRUE);
1364 m_cbOutput->Enable(TRUE);
1365 m_rbOAccept->Enable(TRUE);
1366 m_rbOIgnore->Enable(TRUE);
1367 m_btnOutputStcList->Enable(TRUE);
1368 }
1369
1370 SetDSFormOptionVizStates();
1371 // m_container->FitInside();
1372}
1373
1374void ConnectionEditDialog::ShowInFilter(bool bshow) {
1375 sbSizerInFilter->GetStaticBox()->Show(bshow);
1376 m_rbIAccept->Show(bshow);
1377 m_rbIIgnore->Show(bshow);
1378 m_tcInputStc->Show(bshow);
1379 m_btnInputStcList->Show(bshow);
1380}
1381
1382void ConnectionEditDialog::ShowOutFilter(bool bshow) {
1383 sbSizerOutFilter->GetStaticBox()->Show(bshow);
1384 m_rbOAccept->Show(bshow);
1385 m_rbOIgnore->Show(bshow);
1386 m_tcOutputStc->Show(bshow);
1387 m_btnOutputStcList->Show(bshow);
1388}
1389
1390void ConnectionEditDialog::PreloadControls(ConnectionParams* cp) {
1391 m_cp_original = cp;
1392 SetConnectionParams(cp);
1393}
1394
1395void ConnectionEditDialog::SetConnectionParams(ConnectionParams* cp) {
1396 if (wxNOT_FOUND == m_comboPort->FindString(cp->Port))
1397 m_comboPort->Append(cp->Port);
1398
1399 m_comboPort->Select(m_comboPort->FindString(cp->Port));
1400
1401 m_cbGarminHost->SetValue(cp->Garmin);
1402 m_cbInput->SetValue(cp->IOSelect != DS_TYPE_OUTPUT);
1403 m_cbOutput->SetValue(cp->IOSelect != DS_TYPE_INPUT);
1404 m_cbCheckSKDiscover->SetValue(cp->AutoSKDiscover);
1405
1406 if (cp->InputSentenceListType == WHITELIST)
1407 m_rbIAccept->SetValue(TRUE);
1408 else
1409 m_rbIIgnore->SetValue(TRUE);
1410 if (cp->OutputSentenceListType == WHITELIST)
1411 m_rbOAccept->SetValue(TRUE);
1412 else
1413 m_rbOIgnore->SetValue(TRUE);
1414 m_tcInputStc->SetValue(StringArrayToString(cp->InputSentenceList));
1415 m_tcOutputStc->SetValue(StringArrayToString(cp->OutputSentenceList));
1416 m_choiceBaudRate->Select(
1417 m_choiceBaudRate->FindString(wxString::Format("%d", cp->Baudrate)));
1418 m_choiceSerialProtocol->Select(cp->Protocol); // TODO
1419 m_tNetAddress->SetValue(cp->NetworkAddress);
1420
1421 m_choiceNetDataProtocol->Select(cp->Protocol); // TODO
1422
1423 m_cbMultiCast->SetValue(IsAddressMultiCast(m_tNetAddress->GetValue()));
1424
1425 if (cp->NetworkPort == 0)
1426 m_tNetPort->SetValue(wxEmptyString);
1427 else
1428 m_tNetPort->SetValue(wxString::Format(wxT("%i"), cp->NetworkPort));
1429
1430 if (cp->NetProtocol == TCP)
1431 m_rbNetProtoTCP->SetValue(TRUE);
1432 else if (cp->NetProtocol == UDP)
1433 m_rbNetProtoUDP->SetValue(TRUE);
1434 else if (cp->NetProtocol == GPSD)
1435 m_rbNetProtoGPSD->SetValue(TRUE);
1436 else if (cp->NetProtocol == SIGNALK)
1437 m_rbNetProtoSignalK->SetValue(TRUE);
1438 else
1439 m_rbNetProtoGPSD->SetValue(TRUE);
1440
1441 if (cp->Type == SERIAL) {
1442 m_rbTypeSerial->SetValue(TRUE);
1443 SetNMEAFormToSerial();
1444 SetNMEAFormForSerialProtocol();
1445 } else if (cp->Type == NETWORK) {
1446 m_rbTypeNet->SetValue(TRUE);
1447 SetNMEAFormToNet();
1448 } else if (cp->Type == SOCKETCAN) {
1449 m_rbTypeCAN->SetValue(TRUE);
1450 SetNMEAFormToCAN();
1451
1452 } else if (cp->Type == INTERNAL_GPS) {
1453 if (m_rbTypeInternalGPS) m_rbTypeInternalGPS->SetValue(TRUE);
1454 SetNMEAFormToGPS();
1455 } else if (cp->Type == INTERNAL_BT) {
1456 if (m_rbTypeInternalBT) m_rbTypeInternalBT->SetValue(TRUE);
1457 SetNMEAFormToBT();
1458
1459 // Preset the source selector
1460 wxString bts = cp->NetworkAddress + ";" + cp->GetPortStr();
1461 m_choiceBTDataSources->Clear();
1462 m_choiceBTDataSources->Append(bts);
1463 m_choiceBTDataSources->SetSelection(0);
1464 } else
1465 ClearNMEAForm();
1466
1467 if (cp->Type == SERIAL)
1468 m_tSerialComment->SetValue(cp->UserComment);
1469 else if (cp->Type == NETWORK)
1470 m_tNetComment->SetValue(cp->UserComment);
1471
1472 m_tAuthToken->SetValue(cp->AuthToken);
1473
1474 m_connection_enabled = cp->bEnabled;
1475
1476 // Reset touch flag
1477 connectionsaved = true;
1478}
1479
1480void ConnectionEditDialog::SetUDPNetAddressVisiblity(void) {
1481 if (m_rbNetProtoUDP->GetValue() && !m_cbMultiCast->IsChecked() &&
1482 !m_cbOutput->IsChecked()) {
1483 // m_stNetAddr->Show(FALSE);
1484 // m_tNetAddress->Show(FALSE);
1485 m_tNetAddress->Enable(TRUE);
1486 } else {
1487 m_stNetAddr->Show(TRUE);
1488 m_tNetAddress->Show(TRUE);
1489 m_tNetAddress->Enable(TRUE);
1490 }
1491 if (!m_rbNetProtoUDP->GetValue()) {
1492 m_stNetAddr->Show(TRUE);
1493 m_tNetAddress->Show(TRUE);
1494 m_tNetAddress->Enable(TRUE);
1495 }
1496 if (m_rbNetProtoUDP->GetValue() && m_advanced) {
1497 // m_cbMultiCast->Show();
1498 } else
1499 m_cbMultiCast->Hide();
1500}
1501
1502void ConnectionEditDialog::SetDefaultConnectionParams(void) {
1503 if (m_comboPort && !m_comboPort->IsListEmpty()) {
1504 m_comboPort->Select(0);
1505 m_comboPort->SetValue(wxEmptyString); // These two broke it
1506 }
1507 m_cbGarminHost->SetValue(FALSE);
1508 m_cbInput->SetValue(TRUE);
1509 m_cbOutput->SetValue(FALSE);
1510 m_rbIAccept->SetValue(TRUE);
1511 m_rbOAccept->SetValue(TRUE);
1512 m_tcInputStc->SetValue(wxEmptyString);
1513 m_tcOutputStc->SetValue(wxEmptyString);
1514 m_choiceBaudRate->Select(m_choiceBaudRate->FindString("4800"));
1515 // m_choiceSerialProtocol->Select( cp->Protocol ); // TODO
1516
1517 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1518
1519 m_tNetComment->SetValue(wxEmptyString);
1520 m_tSerialComment->SetValue(wxEmptyString);
1521 m_tAuthToken->SetValue(wxEmptyString);
1522
1523 bool bserial = TRUE;
1524#ifdef __WXGTK__
1525 bserial = FALSE;
1526#endif
1527
1528#ifdef __WXOSX__
1529 bserial = FALSE;
1530#endif
1531
1532#ifdef __ANDROID__
1533 if (m_rbTypeInternalGPS) {
1534 m_rbTypeInternalGPS->SetValue(true);
1535 SetNMEAFormToGPS();
1536 } else {
1537 m_rbTypeNet->SetValue(true);
1538 SetNMEAFormToNet();
1539 }
1540
1541#else
1542 m_rbTypeSerial->SetValue(bserial);
1543 m_rbTypeNet->SetValue(!bserial);
1544 bserial ? SetNMEAFormToSerial() : SetNMEAFormToNet();
1545 m_rbTypeCAN->SetValue(FALSE);
1546#endif
1547
1548 m_connection_enabled = TRUE;
1549
1550 // Reset touch flag
1551 connectionsaved = false;
1552}
1553
1554void ConnectionEditDialog::LayoutDialog() {
1555 gSizerNetProps->Layout();
1556 gSizerSerProps->Layout();
1557 this->Layout();
1558 this->Fit();
1559 GetSizer()->Layout();
1560}
1561
1562void ConnectionEditDialog::UpdateSourceList(bool bResort) {
1563 for (auto* cp : TheConnectionParams()) {
1564 ConnectionParamsPanel* panel = cp->m_optionsPanel;
1565 if (panel) panel->Update(cp);
1566 }
1567
1568 m_scrollWinConnections->Layout();
1569}
1570
1571void ConnectionEditDialog::OnSelectDatasource(wxListEvent& event) {
1572 SetConnectionParams(TheConnectionParams()[event.GetData()]);
1573 m_buttonRemove->Enable();
1574 m_buttonRemove->Show();
1575 event.Skip();
1576}
1577
1578void ConnectionEditDialog::OnDiscoverButton(wxCommandEvent& event) {
1579#if 0 // FIXME (dave)
1580 wxString ip;
1581 int port;
1582 std::string serviceIdent =
1583 std::string("_signalk-ws._tcp.local."); // Works for node.js server
1584
1585 g_Platform->ShowBusySpinner();
1586
1587 if (SignalKDataStream::DiscoverSKServer(serviceIdent, ip, port,
1588 1)) // 1 second scan
1589 {
1590 m_tNetAddress->SetValue(ip);
1591 m_tNetPort->SetValue(wxString::Format(wxT("%i"), port));
1592 UpdateDiscoverStatus(_("Signal K server available."));
1593 } else {
1594 UpdateDiscoverStatus(_("Signal K server not found."));
1595 }
1596 g_Platform->HideBusySpinner();
1597#endif
1598 event.Skip();
1599}
1600
1601void ConnectionEditDialog::UpdateDiscoverStatus(wxString stat) {
1602 m_StaticTextSKServerStatus->SetLabel(stat);
1603}
1604
1605void ConnectionEditDialog::OnBtnIStcs(wxCommandEvent& event) {
1606 const ListType type = m_rbIAccept->GetValue() ? WHITELIST : BLACKLIST;
1607 const wxArrayString list = wxStringTokenize(m_tcInputStc->GetValue(), ",");
1608 SentenceListDlg dlg(m_parent, FILTER_INPUT, type, list);
1609
1610 if (dlg.ShowModal() == wxID_OK) m_tcInputStc->SetValue(dlg.GetSentences());
1611}
1612
1613void ConnectionEditDialog::OnBtnOStcs(wxCommandEvent& event) {
1614 const ListType type = m_rbOAccept->GetValue() ? WHITELIST : BLACKLIST;
1615 const wxArrayString list = wxStringTokenize(m_tcOutputStc->GetValue(), ",");
1616 SentenceListDlg dlg(m_parent, FILTER_OUTPUT, type, list);
1617
1618 if (dlg.ShowModal() == wxID_OK) m_tcOutputStc->SetValue(dlg.GetSentences());
1619}
1620
1621void ConnectionEditDialog::OnNetProtocolSelected(wxCommandEvent& event) {
1622 if (m_rbNetProtoGPSD->GetValue()) {
1623 if (IsDefaultPort(m_tNetPort->GetValue())) {
1624 m_tNetPort->SetValue(DEFAULT_GPSD_PORT);
1625 }
1626 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1627 } else if (m_rbNetProtoUDP->GetValue()) {
1628 if (IsDefaultPort(m_tNetPort->GetValue())) {
1629 m_tNetPort->SetValue(DEFAULT_UDP_PORT);
1630 }
1631 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1632 if (m_cbInput->GetValue() && !m_cbMultiCast->GetValue() &&
1633 m_rbNetProtoUDP->GetValue())
1634 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1635 else if (m_cbOutput->GetValue() && !m_cbMultiCast->GetValue())
1636 m_tNetPort->SetValue(DEFAULT_UDP_OUT_ADDRESS);
1637
1638 if (m_cbInput->GetValue() && m_cbOutput->GetValue())
1639 m_cbOutput->SetValue(false);
1640
1641 } else if (m_rbNetProtoSignalK->GetValue()) {
1642 if (IsDefaultPort(m_tNetPort->GetValue())) {
1643 m_tNetPort->SetValue(DEFAULT_SIGNALK_PORT);
1644 }
1645 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1646 } else if (m_rbNetProtoTCP->GetValue()) {
1647 if (IsDefaultPort(m_tNetPort->GetValue())) {
1648 m_tNetPort->SetValue(DEFAULT_TCP_PORT);
1649 }
1650 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1651 }
1652
1653 SetUDPNetAddressVisiblity();
1654 SetDSFormRWStates();
1655 LayoutDialog();
1656 OnConnValChange(event);
1657}
1658
1659void ConnectionEditDialog::OnRbAcceptInput(wxCommandEvent& event) {
1660 OnConnValChange(event);
1661}
1662void ConnectionEditDialog::OnRbIgnoreInput(wxCommandEvent& event) {
1663 OnConnValChange(event);
1664}
1665
1666void ConnectionEditDialog::OnRbOutput(wxCommandEvent& event) {
1667 OnConnValChange(event);
1668}
1669
1670void ConnectionEditDialog::OnCbInput(wxCommandEvent& event) {
1671 const bool checked = m_cbInput->IsChecked();
1672 ShowInFilter(checked);
1673 if (checked && m_rbNetProtoUDP->GetValue() && m_rbTypeNet->GetValue()) {
1674 m_cbOutput->SetValue(FALSE);
1675
1676 if (!m_cbMultiCast->GetValue()) m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1677 }
1678 SetDSFormRWStates();
1679 LayoutDialog();
1680 if (m_rbTypeNet->GetValue()) SetUDPNetAddressVisiblity();
1681 OnConnValChange(event);
1682}
1683
1684void ConnectionEditDialog::OnCbOutput(wxCommandEvent& event) {
1685 OnConnValChange(event);
1686 const bool checked = m_cbOutput->IsChecked();
1687 m_stPrecision->Enable(checked);
1688 m_choicePrecision->Enable(checked);
1689 ShowOutFilter(checked);
1690
1691 if (!m_cbMultiCast->IsChecked() && m_rbNetProtoUDP->GetValue()) {
1692 if (checked) {
1693 m_tNetAddress->SetValue(
1694 DEFAULT_UDP_OUT_ADDRESS); // IP address for output
1695 // Check for a UDP input connection on the same port
1696 NetworkProtocol proto = UDP;
1697 for (auto* cp : TheConnectionParams()) {
1698 if (cp->NetProtocol == proto &&
1699 cp->NetworkPort == wxAtoi(m_tNetPort->GetValue()) &&
1700 cp->IOSelect == DS_TYPE_INPUT) {
1701 // More: View the filter handler
1702 m_advanced = true;
1703 SetNMEAFormForNetProtocol();
1704 LayoutDialog();
1705
1706 wxString mes;
1707 bool warn = false;
1708 if (cp->bEnabled) {
1709 mes =
1710 _("There is an enabled UDP input connection that uses the "
1711 "same data port.");
1712 mes << "\n"
1713 << _("Please apply a filter on both connections to avoid a "
1714 "feedback loop.");
1715 warn = true;
1716 } else {
1717 mes =
1718 _("There is a disabled UDP Input connection that uses the "
1719 "same Dataport.");
1720 mes << "\n"
1721 << _("If you enable that input please apply a filter on both "
1722 "connections to avoid a feedback loop.");
1723 }
1724 mes << "\n"
1725 << _("Or consider using a different data port for one of them");
1726 if (warn)
1727 OCPNMessageBox(this, mes, _("OpenCPN Warning"),
1728 wxOK | wxICON_EXCLAMATION, 60);
1729 else
1730 OCPNMessageBox(this, mes, _("OpenCPN info"),
1731 wxOK | wxICON_INFORMATION, 60);
1732 break;
1733 }
1734 }
1735 } else {
1736 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS); // IP address for input
1737 }
1738 }
1739
1740 if (checked && m_rbNetProtoUDP->GetValue()) {
1741 m_cbInput->SetValue(FALSE);
1742 }
1743
1744 if (m_rbTypeNet->GetValue()) SetUDPNetAddressVisiblity();
1745 SetDSFormRWStates();
1746 LayoutDialog();
1747}
1748
1749void ConnectionEditDialog::OnCbMultiCast(wxCommandEvent& event) {
1750 const bool checked = m_cbMultiCast->IsChecked();
1751 if (checked) {
1752 if (!IsAddressMultiCast(m_tNetAddress->GetValue())) {
1753 m_tNetAddress->SetValue("224.0.2.21");
1754 }
1755 } else if (m_cbOutput->IsChecked()) {
1756 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS); // IP address for output
1757 } else {
1758 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS); // IP address for input
1759 }
1760
1761 SetUDPNetAddressVisiblity();
1762 LayoutDialog();
1763}
1764
1765void ConnectionEditDialog::OnCollapsedToggle(bool collapsed) {
1766 m_advanced = !collapsed;
1767 if (m_rbTypeNet->GetValue())
1768 SetNMEAFormForNetProtocol();
1769 else
1770 SetNMEAFormForSerialProtocol();
1771 LayoutDialog();
1772}
1773
1774void ConnectionEditDialog::OnCbAdvanced(wxCommandEvent& event) {
1775 if (m_rbTypeNet->GetValue())
1776 SetNMEAFormForNetProtocol();
1777 else
1778 SetNMEAFormForSerialProtocol();
1779 LayoutDialog();
1780}
1781
1782void ConnectionEditDialog::OnShowGpsWindowCheckboxClick(wxCommandEvent& event) {
1783 // if (!m_cbNMEADebug->GetValue()) {
1784 // NMEALogWindow::GetInstance().DestroyWindow();
1785 // } else {
1786 // NMEALogWindow::GetInstance().Create((wxWindow*)(m_parent->GetParent()),
1787 // 35);
1788 //
1789 // // Try to ensure that the log window is at least a little bit visible
1790 // wxRect logRect(NMEALogWindow::GetInstance().GetPosX(),
1791 // NMEALogWindow::GetInstance().GetPosY(),
1792 // NMEALogWindow::GetInstance().GetSizeW(),
1793 // NMEALogWindow::GetInstance().GetSizeH());
1794 // FIXME (leamas)
1795
1796#if 0
1797 if (m_container->GetRect().Contains(logRect)) {
1798 NMEALogWindow::Get().SetPos(
1799 m_container->GetRect().x / 2,
1800 (m_container->GetRect().y +
1801 (m_container->GetRect().height - logRect.height) / 2));
1802 NMEALogWindow::Get().Move();
1803 }
1804#endif
1805 m_parent->Raise();
1806 // }
1807}
1808void ConnectionEditDialog::SetNMEAFormForSerialProtocol() {
1809 bool n0183ctlenabled = (DataProtocol)m_choiceSerialProtocol->GetSelection() ==
1810 DataProtocol::PROTO_NMEA0183;
1811 bool advanced = m_advanced;
1812 ShowNMEACommon(n0183ctlenabled && advanced);
1813 m_cbGarminHost->Show(n0183ctlenabled && advanced);
1814
1815 SetDSFormRWStates();
1816 LayoutDialog();
1817}
1818
1819void ConnectionEditDialog::SetNMEAFormForNetProtocol() {
1820 bool n0183ctlenabled =
1821 (DataProtocol)m_choiceNetDataProtocol->GetSelection() ==
1822 DataProtocol::PROTO_NMEA0183;
1823 bool advanced = m_advanced;
1824 ShowNMEACommon(n0183ctlenabled && advanced);
1825 m_cbGarminHost->Show(n0183ctlenabled && advanced);
1826
1827 SetDSFormRWStates();
1828
1829 LayoutDialog();
1830}
1831
1832void ConnectionEditDialog::OnProtocolChoice(wxCommandEvent& event) {
1833 if (m_rbTypeNet->GetValue())
1834 SetNMEAFormForNetProtocol();
1835 else
1836 SetNMEAFormForSerialProtocol();
1837
1838 OnConnValChange(event);
1839}
1840
1841void ConnectionEditDialog::ApplySettings() {
1842#if 0
1843 g_bfilter_cogsog = m_cbFilterSogCog->GetValue();
1844
1845 long filter_val = 1;
1846 m_tFilterSec->GetValue().ToLong(&filter_val);
1847 g_COGFilterSec =
1848 wxMin(static_cast<int>(filter_val),
1849 60 /*MAX_COGSOG_FILTER_SECONDS*/); // FIXME (dave) should be
1850 g_COGFilterSec = wxMax(g_COGFilterSec, 1);
1851 g_SOGFilterSec = g_COGFilterSec;
1852
1853 g_bMagneticAPB = m_cbAPBMagnetic->GetValue();
1854 g_NMEAAPBPrecision = m_choicePrecision->GetCurrentSelection();
1855
1856 // NMEA Source
1857 // If the stream selected exists, capture some of its existing parameters
1858 // to facility identification and allow stop and restart of the stream
1859 wxString lastAddr;
1860 int lastPort = 0;
1861 NetworkProtocol lastNetProtocol = PROTO_UNDEFINED;
1862 DataProtocol lastDataProtocol = PROTO_NMEA0183;
1863
1864 if (mSelectedConnection) {
1865 ConnectionParams* cpo = mSelectedConnection;
1866 lastAddr = cpo->NetworkAddress;
1867 lastPort = cpo->NetworkPort;
1868 lastNetProtocol = cpo->NetProtocol;
1869 lastDataProtocol = cpo->Protocol;
1870 }
1871
1872 if (!connectionsaved) {
1873 size_t nCurrentPanelCount = TheConnectionParams()->GetCount();
1874 ConnectionParams* cp = NULL;
1875 int old_priority = -1;
1876 {
1877 if (mSelectedConnection) {
1878 cp = mSelectedConnection;
1879 old_priority = cp->Priority;
1880 UpdateConnectionParamsFromControls(cp);
1881 cp->b_IsSetup = false;
1882 // cp->bEnabled = false;
1883 // if (cp->m_optionsPanel)
1884 // cp->m_optionsPanel->SetEnableCheckbox(false);
1885
1886 // delete TheConnectionParams()->Item(itemIndex)->m_optionsPanel;
1887 // old_priority = TheConnectionParams()->Item(itemIndex)->Priority;
1888 // TheConnectionParams()->RemoveAt(itemIndex);
1889 // TheConnectionParams()->Insert(cp, itemIndex);
1890 // mSelectedConnection = cp;
1891 // cp->m_optionsPanel->SetSelected( true );
1892 } else {
1893 cp = CreateConnectionParamsFromSelectedItem();
1894 if (cp) TheConnectionParams()->Add(cp);
1895 }
1896
1897 // Record the previous parameters, if any
1898 if (cp) {
1899 cp->LastNetProtocol = lastNetProtocol;
1900 cp->LastNetworkAddress = lastAddr;
1901 cp->LastNetworkPort = lastPort;
1902 cp->LastDataProtocol = lastDataProtocol;
1903 }
1904
1905 if (TheConnectionParams()->GetCount() != nCurrentPanelCount)
1906 FillSourceList();
1907 else if (old_priority >= 0) {
1908 if (old_priority != cp->Priority) // need resort
1909 UpdateSourceList(true);
1910 else
1911 UpdateSourceList(false);
1912 }
1913
1914 connectionsaved = TRUE;
1915 }
1916 // else {
1917 // ::wxEndBusyCursor();
1918 // if (m_bNMEAParams_shown) event.SetInt(wxID_STOP);
1919 // }
1920
1921 SetSelectedConnectionPanel(nullptr);
1922 }
1923
1924 // Recreate datastreams that are new, or have been edited
1925 for (size_t i = 0; i < TheConnectionParams()->Count(); i++) {
1926 ConnectionParams* cp = TheConnectionParams()->Item(i);
1927
1928 if (cp->b_IsSetup) continue;
1929
1930 // Connection is new, or edited, or disabled
1931
1932 // Terminate and remove any existing driver, if present in registry
1933 StopAndRemoveCommDriver(cp->GetStrippedDSPort(), cp->GetCommProtocol());
1934
1935 // Stop and remove "previous" port, in case other params have changed.
1936 StopAndRemoveCommDriver(cp->GetLastDSPort(), cp->GetLastCommProtocol());
1937
1938 // Internal BlueTooth driver stacks commonly need a time delay to purge
1939 // their buffers, etc. before restating with new parameters...
1940 if (cp->Type == INTERNAL_BT) wxSleep(1);
1941
1942 // Connection has been disabled
1943 if (!cp->bEnabled) continue;
1944
1945 // Make any new or re-enabled drivers
1946 MakeCommDriver(cp);
1947 cp->b_IsSetup = TRUE;
1948 }
1949
1950 g_bGarminHostUpload = m_cbGarminUploadHost->GetValue();
1951 g_GPS_Ident =
1952 m_cbFurunoGP3X->GetValue() ? "FurunoGP3X" : "Generic";
1953#endif
1954}
1955
1957ConnectionEditDialog::CreateConnectionParamsFromSelectedItem() {
1958#if 0
1959 // FIXME (dave) How could this happen?
1960 // if (!m_bNMEAParams_shown) return NULL;
1961
1962 // Special encoding for deleted connection
1963 if (m_rbTypeSerial->GetValue() && m_comboPort->GetValue() == "Deleted")
1964 return NULL;
1965
1966 // We check some values here for consistency.
1967 // If necessary, set defaults so user will see some result, however wrong...
1968
1969 // DataStreams should be Input, Output, or Both
1970 if (!(m_cbInput->GetValue() || m_cbOutput->GetValue())) {
1971 m_cbInput->SetValue(true);
1972 }
1973
1974 if (m_rbTypeSerial->GetValue() && m_comboPort->GetValue() == wxEmptyString) {
1975 m_comboPort->Select(0);
1976 }
1977 // TCP, GPSD and UDP require port field to be set.
1978 // TCP clients, GPSD and UDP output sockets require an address
1979 else if (m_rbTypeNet->GetValue()) {
1980 if (wxAtoi(m_tNetPort->GetValue()) == 0) {
1981 m_tNetPort->SetValue("10110"); // reset to default
1982 }
1983 if (m_tNetAddress->GetValue() == wxEmptyString) {
1984 m_tNetAddress->SetValue("0.0.0.0");
1985 }
1986 } else if (m_rbTypeCAN->GetValue()) {
1987 }
1988
1989 ConnectionParams* pConnectionParams = new ConnectionParams();
1990
1991 UpdateConnectionParamsFromSelectedItem(pConnectionParams);
1992
1994 m_scrollWinConnections, wxID_ANY, wxDefaultPosition, wxDefaultSize,
1995 pConnectionParams, this);
1996 pPanel->SetSelected(false);
1997 boxSizerConnections->Add(pPanel, 0, wxEXPAND | wxALL, 0);
1998 pConnectionParams->m_optionsPanel = pPanel;
1999
2000 return pConnectionParams;
2001#endif
2002 return NULL;
2003}
2004
2005ConnectionParams* ConnectionEditDialog::GetParamsFromControls() {
2006 ConnectionParams* pConnectionParams = new ConnectionParams();
2007 UpdateConnectionParamsFromControls(pConnectionParams);
2008 return pConnectionParams;
2009}
2010
2011ConnectionParams* ConnectionEditDialog::UpdateConnectionParamsFromControls(
2012 ConnectionParams* pConnectionParams) {
2013 pConnectionParams->Valid = TRUE;
2014 if (m_rbTypeSerial->GetValue())
2015 pConnectionParams->Type = SERIAL;
2016 else if (m_rbTypeNet->GetValue())
2017 pConnectionParams->Type = NETWORK;
2018 else if (m_rbTypeInternalGPS && m_rbTypeInternalGPS->GetValue())
2019 pConnectionParams->Type = INTERNAL_GPS;
2020 else if (m_rbTypeInternalBT && m_rbTypeInternalBT->GetValue())
2021 pConnectionParams->Type = INTERNAL_BT;
2022 else if (m_rbTypeCAN && m_rbTypeCAN->GetValue())
2023 pConnectionParams->Type = SOCKETCAN;
2024
2025 if (m_rbTypeNet->GetValue()) {
2026 // Save the existing addr/port to allow closing of existing port
2027 pConnectionParams->LastNetworkAddress = pConnectionParams->NetworkAddress;
2028 pConnectionParams->LastNetworkPort = pConnectionParams->NetworkPort;
2029 pConnectionParams->LastNetProtocol = pConnectionParams->NetProtocol;
2030 pConnectionParams->LastDataProtocol = pConnectionParams->Protocol;
2031
2032 pConnectionParams->NetworkAddress =
2033 m_tNetAddress->GetValue().Trim(false).Trim(true);
2034 pConnectionParams->NetworkPort =
2035 wxAtoi(m_tNetPort->GetValue().Trim(false).Trim(true));
2036 if (m_rbNetProtoTCP->GetValue()) {
2037 pConnectionParams->NetProtocol = TCP;
2038 pConnectionParams->Protocol =
2039 (DataProtocol)m_choiceNetDataProtocol->GetSelection();
2040 } else if (m_rbNetProtoUDP->GetValue()) {
2041 pConnectionParams->NetProtocol = UDP;
2042 pConnectionParams->Protocol =
2043 (DataProtocol)m_choiceNetDataProtocol->GetSelection();
2044 } else if (m_rbNetProtoGPSD->GetValue())
2045 pConnectionParams->NetProtocol = GPSD;
2046 else if (m_rbNetProtoSignalK->GetValue())
2047 pConnectionParams->NetProtocol = SIGNALK;
2048 else
2049 pConnectionParams->NetProtocol = PROTO_UNDEFINED;
2050 }
2051
2052 if (m_rbTypeSerial->GetValue())
2053 pConnectionParams->Protocol =
2054 (DataProtocol)m_choiceSerialProtocol->GetSelection();
2055 else if (m_rbTypeNet->GetValue())
2056 pConnectionParams->Protocol =
2057 (DataProtocol)m_choiceNetDataProtocol->GetSelection();
2058
2059 pConnectionParams->Baudrate = wxAtoi(m_choiceBaudRate->GetStringSelection());
2060 pConnectionParams->ChecksumCheck = true;
2061 pConnectionParams->AutoSKDiscover = m_cbCheckSKDiscover->GetValue();
2062 pConnectionParams->Garmin = m_cbGarminHost->GetValue();
2063 pConnectionParams->InputSentenceList =
2064 wxStringTokenize(m_tcInputStc->GetValue(), ",");
2065 if (m_rbIAccept->GetValue())
2066 pConnectionParams->InputSentenceListType = WHITELIST;
2067 else
2068 pConnectionParams->InputSentenceListType = BLACKLIST;
2069 if (m_cbInput->GetValue()) {
2070 if (m_cbOutput->GetValue()) {
2071 pConnectionParams->IOSelect = DS_TYPE_INPUT_OUTPUT;
2072 } else {
2073 pConnectionParams->IOSelect = DS_TYPE_INPUT;
2074 }
2075 } else
2076 pConnectionParams->IOSelect = DS_TYPE_OUTPUT;
2077
2078 pConnectionParams->OutputSentenceList =
2079 wxStringTokenize(m_tcOutputStc->GetValue(), ",");
2080 if (m_rbOAccept->GetValue())
2081 pConnectionParams->OutputSentenceListType = WHITELIST;
2082 else
2083 pConnectionParams->OutputSentenceListType = BLACKLIST;
2084 pConnectionParams->Port = m_comboPort->GetValue().BeforeFirst(' ');
2085#if defined(__linux__) && !defined(__ANDROID__)
2086 if (pConnectionParams->Type == SERIAL)
2087 CheckSerialAccess(m_parent, pConnectionParams->Port.ToStdString());
2088#endif
2089
2090 if (m_rbTypeCAN && m_rbTypeCAN->GetValue())
2091 pConnectionParams->Protocol = PROTO_NMEA2000;
2092
2093 pConnectionParams->bEnabled = m_connection_enabled;
2094 pConnectionParams->b_IsSetup = FALSE;
2095
2096 if (pConnectionParams->Type == INTERNAL_GPS) {
2097 pConnectionParams->NetworkAddress = "";
2098 pConnectionParams->NetworkPort = 0;
2099 pConnectionParams->NetProtocol = PROTO_UNDEFINED;
2100 pConnectionParams->Baudrate = 0;
2101 pConnectionParams->Port = "Internal GPS";
2102 }
2103
2104 if (pConnectionParams->Type == INTERNAL_BT) {
2105 wxString parms = m_choiceBTDataSources->GetStringSelection();
2106 wxStringTokenizer tkz(parms, ";");
2107 wxString name = tkz.GetNextToken();
2108 wxString mac = tkz.GetNextToken();
2109
2110 pConnectionParams->NetworkAddress = name;
2111 pConnectionParams->Port = mac;
2112 pConnectionParams->NetworkPort = 0;
2113 pConnectionParams->NetProtocol = PROTO_UNDEFINED;
2114 pConnectionParams->Baudrate = 0;
2115 // pConnectionParams->SetAuxParameterStr(m_choiceBTDataSources->GetStringSelection());
2116 }
2117
2118 if (pConnectionParams->Type == SOCKETCAN) {
2119 pConnectionParams->NetworkAddress = "";
2120 pConnectionParams->NetworkPort = 0;
2121 pConnectionParams->NetProtocol = PROTO_UNDEFINED;
2122 pConnectionParams->Baudrate = 0;
2123 pConnectionParams->socketCAN_port =
2124 m_choiceCANSource->GetString(m_choiceCANSource->GetSelection());
2125 }
2126
2127 if (pConnectionParams->Type == SERIAL) {
2128 pConnectionParams->UserComment = m_tSerialComment->GetValue();
2129 } else if (pConnectionParams->Type == NETWORK) {
2130 pConnectionParams->UserComment = m_tNetComment->GetValue();
2131 }
2132 pConnectionParams->AuthToken = m_tAuthToken->GetValue();
2133
2134 return pConnectionParams;
2135}
2136
2137void ConnectionEditDialog::OnPriorityDialog(wxCommandEvent& event) {
2138 PriorityDlg* pdlg = new PriorityDlg(m_parent);
2139 pdlg->ShowModal();
2140 delete pdlg;
2141}
2142void ConnectionEditDialog::ConnectControls() {
2143 // Connect controls
2144 m_rbTypeSerial->Connect(
2145 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2146 wxCommandEventHandler(ConnectionEditDialog::OnTypeSerialSelected), NULL,
2147 this);
2148 m_rbTypeNet->Connect(
2149 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2150 wxCommandEventHandler(ConnectionEditDialog::OnTypeNetSelected), NULL,
2151 this);
2152
2153 m_rbTypeCAN->Connect(
2154 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2155 wxCommandEventHandler(ConnectionEditDialog::OnTypeCANSelected), NULL,
2156 this);
2157
2158 if (m_rbTypeInternalGPS)
2159 m_rbTypeInternalGPS->Connect(
2160 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2161 wxCommandEventHandler(ConnectionEditDialog::OnTypeGPSSelected), NULL,
2162 this);
2163 if (m_rbTypeInternalBT)
2164 m_rbTypeInternalBT->Connect(
2165 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2166 wxCommandEventHandler(ConnectionEditDialog::OnTypeBTSelected), NULL,
2167 this);
2168
2169 // Network connection
2170 m_rbNetProtoTCP->Connect(
2171 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2172 wxCommandEventHandler(ConnectionEditDialog::OnNetProtocolSelected), NULL,
2173 this);
2174 m_rbNetProtoUDP->Connect(
2175 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2176 wxCommandEventHandler(ConnectionEditDialog::OnNetProtocolSelected), NULL,
2177 this);
2178 m_rbNetProtoGPSD->Connect(
2179 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2180 wxCommandEventHandler(ConnectionEditDialog::OnNetProtocolSelected), NULL,
2181 this);
2182 m_rbNetProtoSignalK->Connect(
2183 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2184 wxCommandEventHandler(ConnectionEditDialog::OnNetProtocolSelected), NULL,
2185 this);
2186 m_choiceNetDataProtocol->Connect(
2187 wxEVT_COMMAND_CHOICE_SELECTED,
2188 wxCommandEventHandler(ConnectionEditDialog::OnProtocolChoice), NULL,
2189 this);
2190 m_choiceSerialProtocol->Connect(
2191 wxEVT_COMMAND_CHOICE_SELECTED,
2192 wxCommandEventHandler(ConnectionEditDialog::OnProtocolChoice), NULL,
2193 this);
2194 m_cbMultiCast->Connect(
2195 wxEVT_COMMAND_CHECKBOX_CLICKED,
2196 wxCommandEventHandler(ConnectionEditDialog::OnCbMultiCast), NULL, this);
2197
2198 // input/output control
2199 m_cbInput->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
2200 wxCommandEventHandler(ConnectionEditDialog::OnCbInput),
2201 NULL, this);
2202 m_cbOutput->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
2203 wxCommandEventHandler(ConnectionEditDialog::OnCbOutput),
2204 NULL, this);
2205
2206 if (m_buttonScanBT)
2207 m_buttonScanBT->Connect(
2208 wxEVT_COMMAND_BUTTON_CLICKED,
2209 wxCommandEventHandler(ConnectionEditDialog::OnScanBTClick), NULL, this);
2210
2211 // Input filtering
2212 // m_rbIAccept->Connect(
2213 // wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2214 // wxCommandEventHandler(ConnectionEditDialog::OnRbAcceptInput), NULL,
2215 // this);
2216 // m_rbIIgnore->Connect(
2217 // wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2218 // wxCommandEventHandler(ConnectionEditDialog::OnRbIgnoreInput), NULL,
2219 // this);
2220 // m_tcInputStc->Connect(
2221 // wxEVT_COMMAND_TEXT_UPDATED,
2222 // wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL,
2223 // this);
2224 m_btnInputStcList->Connect(
2225 wxEVT_COMMAND_BUTTON_CLICKED,
2226 wxCommandEventHandler(ConnectionEditDialog::OnBtnIStcs), NULL, this);
2227
2228 // output filtering
2229 m_btnOutputStcList->Connect(
2230 wxEVT_COMMAND_BUTTON_CLICKED,
2231 wxCommandEventHandler(ConnectionEditDialog::OnBtnOStcs), NULL, this);
2232
2233#if 0
2234 m_tNetAddress->Connect(
2235 wxEVT_COMMAND_TEXT_UPDATED,
2236 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2237 m_tNetPort->Connect(wxEVT_COMMAND_TEXT_UPDATED,
2238 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange),
2239 NULL, this);
2240 m_comboPort->Connect(
2241 wxEVT_COMMAND_COMBOBOX_SELECTED,
2242 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2243 m_comboPort->Connect(
2244 wxEVT_COMMAND_TEXT_UPDATED,
2245 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2246 m_choiceBaudRate->Connect(
2247 wxEVT_COMMAND_CHOICE_SELECTED,
2248 wxCommandEventHandler(ConnectionEditDialog::OnBaudrateChoice), NULL, this);
2249 m_choicePriority->Connect(
2250 wxEVT_COMMAND_CHOICE_SELECTED,
2251 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2252 m_choiceCANSource->Connect(
2253 wxEVT_COMMAND_CHOICE_SELECTED,
2254 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2255 m_cbCheckCRC->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
2256 wxCommandEventHandler(ConnectionEditDialog::OnCrcCheck),
2257 NULL, this);
2258 m_cbGarminHost->Connect(
2259 wxEVT_COMMAND_CHECKBOX_CLICKED,
2260 wxCommandEventHandler(ConnectionEditDialog::OnUploadFormatChange), NULL,
2261 this);
2262 m_cbGarminUploadHost->Connect(
2263 wxEVT_COMMAND_CHECKBOX_CLICKED,
2264 wxCommandEventHandler(ConnectionEditDialog::OnUploadFormatChange), NULL,
2265 this);
2266 m_cbFurunoGP3X->Connect(
2267 wxEVT_COMMAND_CHECKBOX_CLICKED,
2268 wxCommandEventHandler(ConnectionEditDialog::OnUploadFormatChange), NULL,
2269 this);
2270 m_cbCheckSKDiscover->Connect(
2271 wxEVT_COMMAND_CHECKBOX_CLICKED,
2272 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2273 m_ButtonSKDiscover->Connect(
2274 wxEVT_COMMAND_BUTTON_CLICKED,
2275 wxCommandEventHandler(ConnectionEditDialog::OnDiscoverButton), NULL, this);
2276
2277 m_rbOAccept->Connect(wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2278 wxCommandEventHandler(ConnectionEditDialog::OnRbOutput),
2279 NULL, this);
2280 m_rbOIgnore->Connect(wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2281 wxCommandEventHandler(ConnectionEditDialog::OnRbOutput),
2282 NULL, this);
2283 m_tcOutputStc->Connect(
2284 wxEVT_COMMAND_TEXT_UPDATED,
2285 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2286 m_cbCheckCRC->Connect(
2287 wxEVT_COMMAND_CHECKBOX_CLICKED,
2288 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2289
2290 m_cbNMEADebug->Connect(
2291 wxEVT_COMMAND_CHECKBOX_CLICKED,
2292 wxCommandEventHandler(ConnectionEditDialog::OnShowGpsWindowCheckboxClick),
2293 NULL, this);
2294 m_cbFilterSogCog->Connect(
2295 wxEVT_COMMAND_CHECKBOX_CLICKED,
2296 wxCommandEventHandler(ConnectionEditDialog::OnValChange), NULL, this);
2297 m_tFilterSec->Connect(wxEVT_COMMAND_TEXT_UPDATED,
2298 wxCommandEventHandler(ConnectionEditDialog::OnValChange),
2299 NULL, this);
2300 m_cbAPBMagnetic->Connect(
2301 wxEVT_COMMAND_CHECKBOX_CLICKED,
2302 wxCommandEventHandler(ConnectionEditDialog::OnValChange), NULL, this);
2303
2304 m_ButtonPriorityDialog->Connect(
2305 wxEVT_COMMAND_BUTTON_CLICKED,
2306 wxCommandEventHandler(ConnectionEditDialog::OnPriorityDialog), NULL, this);
2307
2308 m_tNetComment->Connect(
2309 wxEVT_COMMAND_TEXT_UPDATED,
2310 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2311 m_tSerialComment->Connect(
2312 wxEVT_COMMAND_TEXT_UPDATED,
2313 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2314 m_tAuthToken->Connect(
2315 wxEVT_COMMAND_TEXT_UPDATED,
2316 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2317
2318 if (m_buttonScanBT)
2319 m_buttonScanBT->Connect(
2320 wxEVT_COMMAND_BUTTON_CLICKED,
2321 wxCommandEventHandler(ConnectionEditDialog::OnScanBTClick), NULL, this);
2322#endif
2323}
2324
2325bool ConnectionEditDialog::IsAddressMultiCast(wxString ip) {
2326 wxArrayString bytes = wxSplit(ip, '.');
2327 if (bytes.size() != 4) {
2328 return false;
2329 }
2330 unsigned long ipNum = (wxAtoi(bytes[0]) << 24) + (wxAtoi(bytes[1]) << 16) +
2331 (wxAtoi(bytes[2]) << 8) + wxAtoi(bytes[3]);
2332 unsigned long multicastStart = (224 << 24);
2333 unsigned long multicastEnd = (239 << 24) + (255 << 16) + (255 << 8) + 255;
2334 return ipNum >= multicastStart && ipNum <= multicastEnd;
2335}
2336
2337bool ConnectionEditDialog::IsDefaultPort(wxString address) {
2338 return (address == DEFAULT_TCP_PORT) || (address == DEFAULT_UDP_PORT) ||
2339 (address == DEFAULT_SIGNALK_PORT) || (address == DEFAULT_GPSD_PORT);
2340}
2341
2342bool ConnectionEditDialog::IsAddressBroadcast(wxString ip) {
2343 wxArrayString bytes = wxSplit(ip, '.');
2344 if (bytes.size() != 4) {
2345 std::cerr << "Invalid IP format." << std::endl;
2346 return false;
2347 }
2348 return wxAtoi(bytes[3]) == 255;
2349}
2350
2351SentenceListDlg::SentenceListDlg(wxWindow* parent, FilterDirection dir,
2352 ListType type, const wxArrayString& list)
2353 : wxDialog(parent, wxID_ANY, _("Sentence Filter"), wxDefaultPosition,
2354 wxSize(280, 420)),
2355 m_type(type),
2356 m_dir(dir),
2357 m_sentences(NMEA0183().GetRecognizedArray()) {
2358 m_sentences.Sort();
2359 wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
2360 wxBoxSizer* secondSizer = new wxBoxSizer(wxHORIZONTAL);
2361 wxStaticBox* pclbBox = new wxStaticBox(this, wxID_ANY, GetBoxLabel());
2362 wxStaticBoxSizer* stcSizer = new wxStaticBoxSizer(pclbBox, wxVERTICAL);
2363 m_clbSentences = new wxCheckListBox(this, wxID_ANY, wxDefaultPosition,
2364 wxDefaultSize, m_sentences);
2365 wxBoxSizer* btnEntrySizer = new wxBoxSizer(wxVERTICAL);
2366 wxButton* btnCheckAll = new wxButton(this, wxID_ANY, _("Select All"));
2367 wxButton* btnClearAll = new wxButton(this, wxID_ANY, _("Clear All"));
2368 wxButton* btnAdd = new wxButton(this, wxID_ANY, _("Add"));
2369 m_btnDel = new wxButton(this, wxID_ANY, _("Delete"));
2370 m_btnDel->Disable();
2371 wxStdDialogButtonSizer* btnSizer = new wxStdDialogButtonSizer();
2372 wxButton* btnOK = new wxButton(this, wxID_OK);
2373 wxButton* btnCancel = new wxButton(this, wxID_CANCEL, _("Cancel"));
2374
2375 secondSizer->Add(stcSizer, 1, wxALL | wxEXPAND, 5);
2376 stcSizer->Add(m_clbSentences, 1, wxALL | wxEXPAND, 5);
2377 btnEntrySizer->Add(btnCheckAll, 0, wxALL, 5);
2378 btnEntrySizer->Add(btnClearAll, 0, wxALL, 5);
2379 btnEntrySizer->AddSpacer(1);
2380 btnEntrySizer->Add(btnAdd, 0, wxALL, 5);
2381 btnEntrySizer->Add(m_btnDel, 0, wxALL, 5);
2382 secondSizer->Add(btnEntrySizer, 0, wxALL | wxEXPAND, 5);
2383 mainSizer->Add(secondSizer, 1, wxEXPAND, 5);
2384 btnSizer->AddButton(btnOK);
2385 btnSizer->AddButton(btnCancel);
2386 btnSizer->Realize();
2387 mainSizer->Add(btnSizer, 0, wxALL | wxEXPAND, 5);
2388
2389 SetSizer(mainSizer);
2390 mainSizer->SetSizeHints(this);
2391 Centre();
2392
2393 // Connect Events
2394 btnAdd->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
2395 wxCommandEventHandler(SentenceListDlg::OnAddClick), NULL,
2396 this);
2397 m_btnDel->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
2398 wxCommandEventHandler(SentenceListDlg::OnDeleteClick), NULL,
2399 this);
2400 m_clbSentences->Connect(wxEVT_COMMAND_LISTBOX_SELECTED,
2401 wxCommandEventHandler(SentenceListDlg::OnCLBSelect),
2402 NULL, this);
2403 btnCheckAll->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
2404 wxCommandEventHandler(SentenceListDlg::OnCheckAllClick),
2405 NULL, this);
2406 btnClearAll->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
2407 wxCommandEventHandler(SentenceListDlg::OnClearAllClick),
2408 NULL, this);
2409
2410 Populate(list);
2411}
2412
2413wxString SentenceListDlg::GetBoxLabel(void) const {
2414 if (m_dir == FILTER_OUTPUT)
2415 return m_type == WHITELIST ? _("Transmit sentences") : _("Drop sentences");
2416 else
2417 return m_type == WHITELIST ? _("Accept only sentences")
2418 : _("Ignore sentences");
2419}
2420
2421void SentenceListDlg::Populate(const wxArrayString& list) {
2422 if (m_dir == FILTER_OUTPUT) {
2423 wxString s;
2424 m_sentences.Add(g_TalkerIdText + wxString("RMB"));
2425 m_sentences.Add(g_TalkerIdText + wxString("RMC"));
2426 m_sentences.Add(g_TalkerIdText + wxString("APB"));
2427 m_sentences.Add(g_TalkerIdText + wxString("XTE"));
2428 }
2429 m_sentences.Add("AIVDM");
2430 m_sentences.Add("AIVDO");
2431 m_sentences.Add("FRPOS");
2432 m_sentences.Add(g_TalkerIdText);
2433 m_sentences.Add("CD");
2434 m_sentences.Sort();
2435 m_clbSentences->Clear();
2436 m_clbSentences->InsertItems(m_sentences, 0);
2437
2438 wxArrayString new_strings;
2439
2440 if (list.Count() == 0) {
2441 for (size_t i = 0; i < m_clbSentences->GetCount(); ++i)
2442 m_clbSentences->Check(i, m_type == WHITELIST);
2443 } else {
2444 for (size_t i = 0; i < list.Count(); ++i) {
2445 int item = m_clbSentences->FindString(list[i]);
2446 if (item != wxNOT_FOUND)
2447 m_clbSentences->Check(item);
2448 else
2449 new_strings.Add(list[i]);
2450 }
2451 if (new_strings.GetCount()) {
2452 m_clbSentences->InsertItems(new_strings, m_clbSentences->GetCount());
2453 for (size_t i = 0; i < new_strings.GetCount(); ++i) {
2454 int item = m_clbSentences->FindString(new_strings[i]);
2455 if (item != wxNOT_FOUND) m_clbSentences->Check(item);
2456 }
2457 }
2458 }
2459}
2460
2461wxString SentenceListDlg::GetSentences(void) {
2462 wxArrayString retString;
2463 for (size_t i = 0; i < m_clbSentences->GetCount(); i++) {
2464 if (m_clbSentences->IsChecked(i))
2465 retString.Add(m_clbSentences->GetString(i));
2466 }
2467 return StringArrayToString(retString);
2468}
2469
2470void SentenceListDlg::OnCLBSelect(wxCommandEvent& e) {
2471 // Only activate the "Delete" button if the selection is not in the standard
2472 // list
2473 m_btnDel->Enable(m_sentences.Index(e.GetString()) == wxNOT_FOUND);
2474}
2475
2476void SentenceListDlg::OnAddClick(wxCommandEvent& event) {
2477#ifdef __ANDROID__
2478 androidDisableRotation();
2479#endif
2480
2481 wxTextEntryDialog textdlg(
2482 this,
2483 _("Enter the NMEA sentence (2, 3 or 5 characters)\n or a valid REGEX "
2484 "expression (6 characters or longer)"),
2485 _("Enter the NMEA sentence"));
2486
2487 textdlg.SetTextValidator(wxFILTER_ASCII);
2488 int result = textdlg.ShowModal();
2489
2490#ifdef __ANDROID__
2491 androidEnableRotation();
2492#endif
2493
2494 if (result == wxID_CANCEL) return;
2495 wxString stc = textdlg.GetValue();
2496
2497 if (stc.Length() == 2 || stc.Length() == 3 || stc.Length() == 5) {
2498 m_clbSentences->Append(stc);
2499 m_clbSentences->Check(m_clbSentences->FindString(stc));
2500 return;
2501 } else if (stc.Length() < 2) {
2502 OCPNMessageBox(
2503 this,
2504 _("An NMEA sentence is generally 3 characters long (like RMC, GGA etc.)\n \
2505 It can also have a two letter prefix identifying the source, or TALKER, of the message.\n \
2506 The whole sentences then looks like GPGGA or AITXT.\n \
2507 You may filter out all the sentences with certain TALKER prefix (like GP, AI etc.).\n \
2508 The filter also accepts Regular Expressions (REGEX) with 6 or more characters. \n\n"),
2509 _("OpenCPN Info"));
2510 return;
2511 }
2512
2513 else {
2514 // Verify that a longer text entry is a valid RegEx
2515 wxRegEx r(stc);
2516 if (r.IsValid()) {
2517 m_clbSentences->Append(stc);
2518 m_clbSentences->Check(m_clbSentences->FindString(stc));
2519 return;
2520 } else {
2521 OCPNMessageBox(this, _("REGEX syntax error: \n") + stc,
2522 _("OpenCPN Info"));
2523 return;
2524 }
2525 }
2526}
2527
2528void SentenceListDlg::OnDeleteClick(wxCommandEvent& event) {
2529 m_clbSentences->Delete(m_clbSentences->GetSelection());
2530}
2531
2532void SentenceListDlg::OnClearAllClick(wxCommandEvent& event) {
2533 for (size_t i = 0; i < m_clbSentences->GetCount(); i++)
2534 m_clbSentences->Check(i, FALSE);
2535}
2536
2537void SentenceListDlg::OnCheckAllClick(wxCommandEvent& event) {
2538 for (size_t i = 0; i < m_clbSentences->GetCount(); i++)
2539 m_clbSentences->Check(i, TRUE);
2540}
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
Provides platform-specific support utilities for OpenCPN.
void Init(const KeyProvider &kp, std::function< void(ObservedEvt &ev)> action)
Initiate an object yet not listening.
Definition observable.h:274
Custom event class for OpenCPN's notification system.
Dialog and support code for editing a connection.
wxFont * GetOCPNScaledFont(wxString item, int default_size)
Retrieves a font from FontMgr, optionally scaled for physical readability.
Definition gui_lib.cpp:54
General purpose GUI support.
std::vector< std::string > split(const char *token_string, const std::string &delimiter)
Return vector of items in s separated by delimiter.
std::string trim(std::string s)
Strip possibly trailing and/or leading space characters in s.
PlugIn Object Definition/API.
Miscellaneous utilities, many of which string related.
Suspend/resume and new devices events exchange point.
bool CheckSerialAccess(wxWindow *parent, const std::string device)
Run checks and possible dialogs to ensure device is accessible.
Access checks for comm devices and dongle.