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