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