35#include <wx/jsonreader.h>
36#include <wx/jsonval.h>
37#include <wx/jsonwriter.h>
38#include <wx/tokenzr.h>
40#include "comm_driver.h"
41#include "comm_drv_factory.h"
42#include "comm_drv_n0183_net.h"
43#include "comm_drv_n0183_serial.h"
44#include "comm_drv_registry.h"
45#include "comm_n0183_output.h"
46#include "config_vars.h"
47#include "conn_params.h"
51#include "NMEALogWindow.h"
54#include "garmin_wrapper.h"
59void LogBroadcastOutputMessageColor(
const wxString &msg,
60 const wxString &stream_name,
61 const wxString &color) {
64 if (NMEALogWindow::Get().Active()) {
65 wxDateTime now = wxDateTime::Now();
68 ss = now.FormatISOTime();
70 ss.Prepend(_T(
"--> "));
72 ss.Append(stream_name);
77 NMEALogWindow::Get().Add(ss.ToStdString());
83void BroadcastNMEA0183Message(
const wxString &msg) {
85 auto& registry = CommDriverRegistry::GetInstance();
86 const std::vector<std::shared_ptr<AbstractCommDriver>>& drivers = registry.GetDrivers();
88 for (
auto& driver : drivers) {
89 if (driver->bus == NavAddr::Bus::N0183) {
92 std::dynamic_pointer_cast<CommDriverN0183Serial>(driver);
94 params = drv_serial->GetParams();
96 auto drv_net = std::dynamic_pointer_cast<CommDriverN0183Net>(driver);
98 params = drv_net->GetParams();
102 if (params.IOSelect == DS_TYPE_INPUT_OUTPUT ||
103 params.IOSelect == DS_TYPE_OUTPUT) {
104 bool bout_filter = params.SentencePassesFilter(msg, FILTER_OUTPUT);
106 std::string
id = msg.ToStdString().substr(1,5);
107 auto msg_out = std::make_shared<Nmea0183Msg>(
id,
109 std::make_shared<NavAddr0183>(driver->iface));
111 bool bxmit_ok = driver->SendMessage(msg_out, std::make_shared<NavAddr0183>(driver->iface));
114 LogBroadcastOutputMessageColor(msg, params.GetDSPort(), _T(
"<BLUE>"));
116 LogBroadcastOutputMessageColor(msg, params.GetDSPort(), _T(
"<RED>"));
119 LogBroadcastOutputMessageColor(msg, params.GetDSPort(), _T(
"<CORAL>"));
130std::shared_ptr<AbstractCommDriver> CreateOutputConnection(
const wxString &com_name,
131 std::shared_ptr<AbstractCommDriver> &old_driver,
133 bool &btempStream,
bool &b_restoreStream){
135 std::shared_ptr<AbstractCommDriver> driver;
136 auto& registry = CommDriverRegistry::GetInstance();
137 const std::vector<std::shared_ptr<AbstractCommDriver>>& drivers = registry.GetDrivers();
139 if (com_name.Lower().StartsWith(
"serial")) {
140 wxString comx = com_name.AfterFirst(
':');
141 comx = comx.BeforeFirst(
' ');
143 old_driver = FindDriver(drivers, comx.ToStdString());
144 wxLogDebug(
"Looking for old stream %s", com_name);
147 auto drv_serial_n0183 =
148 std::dynamic_pointer_cast<CommDriverN0183Serial>(old_driver);
149 if (drv_serial_n0183) {
150 params_save = drv_serial_n0183->GetParams();
152 registry.Deactivate(old_driver);
154 b_restoreStream =
true;
158 driver = FindDriver(drivers, com_name.ToStdString());
161 if (com_name.Lower().StartsWith(
"serial")) {
167 baud = params_save.Baudrate;
174 cp.SetPortStr(com_name);
176 cp.IOSelect = DS_TYPE_INPUT_OUTPUT;
178 driver = MakeCommDriver(&cp);
184 auto drv_serial_n0183 =
185 std::dynamic_pointer_cast<CommDriverN0183Serial>(driver);
186 if (drv_serial_n0183) {
189 while (!drv_serial_n0183->IsSecThreadActive() && (timeout < 50)) {
194 if (!drv_serial_n0183->IsSecThreadActive()) {
195 wxString msg(_T(
"-->GPS Port:"));
197 msg += _T(
" ...Could not be opened for writing");
204 else if (com_name.Find(
"Bluetooth") != wxNOT_FOUND) {
208 wxStringTokenizer tkz(com_name, _T(
";"));
209 wxString name = tkz.GetNextToken();
210 wxString mac = tkz.GetNextToken();
223 else if (com_name.Lower().StartsWith(
"udp") ||
224 com_name.Lower().StartsWith(
"tcp")) {
225 std::shared_ptr<CommDriverN0183Net> drv_net_n0183;
228 NetworkProtocol protocol = UDP;
229 if (com_name.Lower().StartsWith(
"tcp")) protocol = TCP;
230 wxStringTokenizer tkz(com_name, _T(
":"));
231 wxString token = tkz.GetNextToken();
232 wxString address = tkz.GetNextToken();
233 token = tkz.GetNextToken();
239 cp.NetProtocol = protocol;
240 cp.NetworkAddress = address;
241 cp.NetworkPort = port;
242 cp.IOSelect = DS_TYPE_INPUT_OUTPUT;
244 driver = MakeCommDriver(&cp);
248 std::dynamic_pointer_cast<CommDriverN0183Net>(driver);
250 if (com_name.Lower().StartsWith(
"tcp")) {
260 bool bconnected =
false;
261 while (!bconnected && (loopCount > 0)) {
262 if (drv_net_n0183->GetSock()->IsConnected()) {
278 registry.Deactivate(driver);
289int SendRouteToGPS_N0183(
Route *pr,
const wxString &com_name,
290 bool bsend_waypoints) {
294 bool b_restoreStream =
false;
295 bool btempStream =
false;
296 std::shared_ptr<AbstractCommDriver> old_driver;
297 std::shared_ptr<AbstractCommDriver> driver;
298 auto& registry = CommDriverRegistry::GetInstance();
300 driver = CreateOutputConnection(com_name, old_driver,
301 params_save, btempStream, b_restoreStream);
305 auto drv_n0183 = std::dynamic_pointer_cast<CommDriverN0183>(driver);
306 auto address = std::make_shared<NavAddr0183>(drv_n0183->iface);
311 if (g_GPS_Ident == _T(
"FurunoGP3X")) {
312 if (pr->pRoutePointList->GetCount() > 30) {
316 _T(
"Routes containing more than 30 waypoints must be split before ")
318 _(
"Route Upload"), 10, style,
false, wxDefaultPosition);
319 int reply = dlg->ShowModal();
328 if (com_name.Upper().Matches(_T(
"*GARMIN*")))
333 int v_init = Garmin_GPS_Init(wxString(_T(
"usb:")));
336 wxString msg(_T(
" Garmin USB GPS could not be initialized"));
338 msg.Printf(_T(
" Error Code is %d"), v_init);
340 msg = _T(
" LastGarminError is: ");
341 msg += GetLastGarminError();
344 ret_val = ERR_GARMIN_INITIALIZE;
346 wxLogMessage(_T(
"Garmin USB Initialized"));
348 wxString msg = _T(
"USB Unit identifies as: ");
349 wxString GPS_Unit = Garmin_GPS_GetSaveString();
353 wxLogMessage(_T(
"Sending Routes..."));
354 int ret1 = Garmin_GPS_SendRoute(wxString(_T(
"usb:")), pr,
358 wxLogMessage(_T(
" Error Sending Routes"));
360 msg = _T(
" LastGarminError is: ");
361 msg += GetLastGarminError();
364 ret_val = ERR_GARMIN_GENERAL;
376 if (g_bGarminHostUpload) {
384 wxString short_com = com_name.Mid(7);
387 int v_init = Garmin_GPS_Init(short_com);
389 wxString msg(_T(
"Garmin GPS could not be initialized on port: "));
392 err.Printf(_T(
" Error Code is %d"), v_init);
395 msg += _T(
"\n LastGarminError is: ");
396 msg += GetLastGarminError();
400 ret_val = ERR_GARMIN_INITIALIZE;
403 wxString msg(_T(
"Sent Route to Garmin GPS on port: "));
405 msg += _T(
"\n Unit identifies as: ");
406 wxString GPS_Unit = Garmin_GPS_GetSaveString();
418 lret_val = Garmin_GPS_SendRoute(short_com, pr, 0);
420 wxString msg(_T(
"Error Sending Route to Garmin GPS on port: "));
423 err.Printf(_T(
" Error Code is %d"), ret_val);
425 msg += _T(
"\n LastGarminError is: ");
426 msg += GetLastGarminError();
431 ret_val = ERR_GARMIN_GENERAL;
454 oNMEA0183.TalkerID = _T (
"EC" );
456 int nProg = pr->pRoutePointList->GetCount() + 1;
460 int progress_stall = 500;
461 if (pr->pRoutePointList->GetCount() > 10) progress_stall = 200;
466 if (bsend_waypoints) {
467 wxRoutePointListNode *node = pr->pRoutePointList->GetFirst();
473 if (g_GPS_Ident == _T(
"Generic")) {
475 oNMEA0183.Wpl.Position.Latitude.Set(-prp->m_lat, _T (
"S" ));
477 oNMEA0183.Wpl.Position.Latitude.Set(prp->m_lat, _T (
"N" ));
480 oNMEA0183.Wpl.Position.Longitude.Set(-prp->m_lon, _T (
"W" ));
482 oNMEA0183.Wpl.Position.Longitude.Set(prp->m_lon, _T (
"E" ));
484 oNMEA0183.Wpl.To = prp->GetName().Truncate(g_maxWPNameLength);
486 oNMEA0183.Wpl.Write(snt);
488 }
else if (g_GPS_Ident == _T(
"FurunoGP3X")) {
491 wxString talker_save = g_TalkerIdText;
492 g_TalkerIdText.Clear();
494 oNMEA0183.TalkerID = _T (
"PFEC," );
497 oNMEA0183.GPwpl.Position.Latitude.Set(-prp->m_lat, _T (
"S" ));
499 oNMEA0183.GPwpl.Position.Latitude.Set(prp->m_lat, _T (
"N" ));
502 oNMEA0183.GPwpl.Position.Longitude.Set(-prp->m_lon, _T (
"W" ));
504 oNMEA0183.GPwpl.Position.Longitude.Set(prp->m_lon, _T (
"E" ));
506 wxString name = prp->GetName();
507 name += _T(
"000000");
508 name.Truncate(g_maxWPNameLength);
509 oNMEA0183.GPwpl.To = name;
511 oNMEA0183.GPwpl.Write(snt);
513 g_TalkerIdText = talker_save;
516 wxString payload = snt.Sentence;
528 auto msg_out = std::make_shared<Nmea0183Msg>(std::string(
"ECWPL"),
529 snt.Sentence.ToStdString(),
532 drv_n0183->SendMessage(msg_out, address);
533 if (g_GPS_Ident != _T(
"FurunoGP3X"))
534 drv_n0183->SendMessage(msg_out, address);
538 wxString msg(_T(
"-->GPS Port:"));
540 msg += _T(
" Sentence: ");
551 wxMilliSleep(progress_stall);
553 node = node->GetNext();
562 unsigned int max_length = 76;
563 unsigned int max_wp = 2;
567 if (g_GPS_Ident == _T(
"FurunoGP3X")) {
573 wxString talker_save = g_TalkerIdText;
574 if (g_GPS_Ident == _T(
"FurunoGP3X")) g_TalkerIdText.Clear();
576 oNMEA0183.Rte.Empty();
577 oNMEA0183.Rte.TypeOfRoute = CompleteRoute;
579 if (pr->m_RouteNameString.IsEmpty())
580 oNMEA0183.Rte.RouteName = _T (
"1" );
582 oNMEA0183.Rte.RouteName = pr->m_RouteNameString;
584 if (g_GPS_Ident == _T(
"FurunoGP3X")) {
585 oNMEA0183.Rte.RouteName = _T (
"01" );
586 oNMEA0183.TalkerID = _T (
"GP" );
587 oNMEA0183.Rte.m_complete_char =
'C';
588 oNMEA0183.Rte.m_skip_checksum = 1;
591 oNMEA0183.Rte.total_number_of_messages = 1;
592 oNMEA0183.Rte.message_number = 1;
595 wxRoutePointListNode *node = pr->pRoutePointList->GetFirst();
598 wxString name = prp->GetName().Truncate(g_maxWPNameLength);
600 if (g_GPS_Ident == _T(
"FurunoGP3X")) {
601 name = prp->GetName();
602 name += _T(
"000000");
603 name.Truncate(g_maxWPNameLength);
604 name.Prepend(_T(
" "));
608 oNMEA0183.Rte.AddWaypoint(name);
609 node = node->GetNext();
612 oNMEA0183.Rte.Write(snt);
614 if ((snt.Sentence.Len() > max_length) ||
615 (pr->pRoutePointList->GetCount() >
621 tNMEA0183.TalkerID = _T (
"EC" );
623 tNMEA0183.Rte.Empty();
624 tNMEA0183.Rte.TypeOfRoute = CompleteRoute;
626 if (g_GPS_Ident != _T(
"FurunoGP3X")) {
627 if (pr->m_RouteNameString.IsEmpty())
628 tNMEA0183.Rte.RouteName = _T (
"1" );
630 tNMEA0183.Rte.RouteName = pr->m_RouteNameString;
633 tNMEA0183.Rte.RouteName = _T (
"01" );
636 tNMEA0183.Rte.Write(tsnt);
638 unsigned int tare_length = tsnt.Sentence.Len();
641 wxArrayString sentence_array;
645 bool bnew_sentence =
true;
647 unsigned int wp_count = 0;
649 wxRoutePointListNode *node = pr->pRoutePointList->GetFirst();
652 unsigned int name_len =
653 prp->GetName().Truncate(g_maxWPNameLength).Len();
654 if (g_GPS_Ident == _T(
"FurunoGP3X"))
658 sent_len = tare_length;
659 sent_len += name_len + 1;
660 bnew_sentence =
false;
661 node = node->GetNext();
665 if ((sent_len + name_len > max_length) || (wp_count >= max_wp)) {
667 bnew_sentence =
true;
669 if (wp_count == max_wp)
670 sent_len += name_len;
672 sent_len += name_len + 1;
674 node = node->GetNext();
681 int final_total = n_total;
683 bnew_sentence =
true;
685 node = pr->pRoutePointList->GetFirst();
688 wxString name = prp->GetName().Truncate(g_maxWPNameLength);
689 if (g_GPS_Ident == _T(
"FurunoGP3X")) {
690 name = prp->GetName();
691 name += _T(
"000000");
692 name.Truncate(g_maxWPNameLength);
693 name.Prepend(_T(
" "));
697 unsigned int name_len = name.Len();
700 sent_len = tare_length;
701 sent_len += name_len + 1;
702 bnew_sentence =
false;
704 oNMEA0183.Rte.Empty();
705 oNMEA0183.Rte.TypeOfRoute = CompleteRoute;
707 if (g_GPS_Ident != _T(
"FurunoGP3X")) {
708 if (pr->m_RouteNameString.IsEmpty())
709 oNMEA0183.Rte.RouteName = _T (
"1" );
711 oNMEA0183.Rte.RouteName = pr->m_RouteNameString;
713 oNMEA0183.Rte.RouteName = _T (
"01" );
716 oNMEA0183.Rte.total_number_of_messages = final_total;
717 oNMEA0183.Rte.message_number = n_run;
718 snt.Sentence.Clear();
721 oNMEA0183.Rte.AddWaypoint(name);
722 node = node->GetNext();
724 if ((sent_len + name_len > max_length) || (wp_count >= max_wp)) {
726 bnew_sentence =
true;
728 oNMEA0183.Rte.Write(snt);
730 sentence_array.Add(snt.Sentence);
732 sent_len += name_len + 1;
733 oNMEA0183.Rte.AddWaypoint(name);
735 node = node->GetNext();
740 oNMEA0183.Rte.Write(snt);
741 if (snt.Sentence.Len() > tare_length) sentence_array.Add(snt.Sentence);
743 for (
unsigned int ii = 0; ii < sentence_array.GetCount(); ii++) {
744 wxString sentence = sentence_array[ii];
746 auto msg_out = std::make_shared<Nmea0183Msg>(std::string(
"ECRTE"),
747 sentence.ToStdString(),
749 drv_n0183->SendMessage(msg_out, address);
753 wxString msg(_T(
"-->GPS Port:"));
755 msg += _T(
" Sentence: ");
760 wxMilliSleep(progress_stall);
764 auto msg_out = std::make_shared<Nmea0183Msg>(std::string(
"ECRTE"),
765 snt.Sentence.ToStdString(),
767 drv_n0183->SendMessage(msg_out, address);
771 wxString msg(_T(
"-->GPS Port:"));
773 msg += _T(
" Sentence: ");
779 if (g_GPS_Ident == _T(
"FurunoGP3X")) {
780 wxString name = pr->GetName();
781 if (name.IsEmpty()) name = _T(
"RTECOMMENT");
783 rte.Printf(_T(
"$PFEC,GPrtc,01,"));
784 rte += name.Left(16);
786 rtep.Printf(_T(
",%c%c"), 0x0d, 0x0a);
789 auto msg_out = std::make_shared<Nmea0183Msg>(std::string(
"GPRTC"),
792 drv_n0183->SendMessage(msg_out, address);
796 wxString msg(_T(
"-->GPS Port:"));
798 msg += _T(
" Sentence: ");
804 term.Printf(_T(
"$PFEC,GPxfr,CTL,E%c%c"), 0x0d, 0x0a);
806 auto msg_outf = std::make_shared<Nmea0183Msg>(std::string(
"GPRTC"),
809 drv_n0183->SendMessage(msg_outf, address);
813 msg = wxString(_T(
"-->GPS Port:"));
815 msg += _T(
" Sentence: ");
827 wxMilliSleep(progress_stall);
833 registry.Deactivate(driver);
835 if (g_GPS_Ident == _T(
"FurunoGP3X")) g_TalkerIdText = talker_save;
840 if (b_restoreStream && old_driver)
841 MakeCommDriver(¶ms_save);
846int SendWaypointToGPS_N0183(
RoutePoint *prp,
const wxString &com_name) {
850 bool b_restoreStream =
false;
851 bool btempStream =
false;
852 std::shared_ptr<AbstractCommDriver> old_driver;
853 std::shared_ptr<AbstractCommDriver> driver;
854 auto& registry = CommDriverRegistry::GetInstance();
856 driver = CreateOutputConnection(com_name, old_driver,
857 params_save, btempStream, b_restoreStream);
861 auto drv_n0183 = std::dynamic_pointer_cast<CommDriverN0183>(driver);
862 auto address = std::make_shared<NavAddr0183>(drv_n0183->iface);
867 if (com_name.Upper().Matches(_T(
"*GARMIN*")))
872 int v_init = Garmin_GPS_Init(wxString(_T(
"usb:")));
875 wxString msg(_T(
" Garmin USB GPS could not be initialized"));
877 msg.Printf(_T(
" Error Code is %d"), v_init);
879 msg = _T(
" LastGarminError is: ");
880 msg += GetLastGarminError();
883 ret_val = ERR_GARMIN_INITIALIZE;
885 wxLogMessage(_T(
"Garmin USB Initialized"));
887 wxString msg = _T(
"USB Unit identifies as: ");
888 wxString GPS_Unit = Garmin_GPS_GetSaveString();
892 wxLogMessage(_T(
"Sending Waypoint..."));
895 RoutePointList rplist;
898 int ret1 = Garmin_GPS_SendWaypoints(wxString(_T(
"usb:")), &rplist);
901 wxLogMessage(_T(
" Error Sending Waypoint to Garmin USB"));
903 msg = _T(
" LastGarminError is: ");
904 msg += GetLastGarminError();
907 ret_val = ERR_GARMIN_GENERAL;
920 if (g_bGarminHostUpload) {
921 RoutePointList rplist;
924 wxString short_com = com_name.Mid(7);
927 int v_init = Garmin_GPS_Init(short_com);
929 wxString msg(_T(
"Garmin GPS could not be initialized on port: "));
932 err.Printf(_T(
" Error Code is %d"), v_init);
935 msg += _T(
"\n LastGarminError is: ");
936 msg += GetLastGarminError();
940 ret_val = ERR_GARMIN_INITIALIZE;
943 wxString msg(_T(
"Sent waypoint(s) to Garmin GPS on port: "));
945 msg += _T(
"\n Unit identifies as: ");
946 wxString GPS_Unit = Garmin_GPS_GetSaveString();
954 ret_val = Garmin_GPS_SendWaypoints(short_com, &rplist);
956 wxString msg(_T(
"Error Sending Waypoint(s) to Garmin GPS on port: "));
959 err.Printf(_T(
" Error Code is %d"), ret_val);
962 msg += _T(
"\n LastGarminError is: ");
963 msg += GetLastGarminError();
967 ret_val = ERR_GARMIN_GENERAL;
980 oNMEA0183.TalkerID = _T (
"EC" );
985 if (g_GPS_Ident == _T(
"Generic")) {
987 oNMEA0183.Wpl.Position.Latitude.Set(-prp->m_lat, _T (
"S" ));
989 oNMEA0183.Wpl.Position.Latitude.Set(prp->m_lat, _T (
"N" ));
992 oNMEA0183.Wpl.Position.Longitude.Set(-prp->m_lon, _T (
"W" ));
994 oNMEA0183.Wpl.Position.Longitude.Set(prp->m_lon, _T (
"E" ));
996 oNMEA0183.Wpl.To = prp->GetName().Truncate(g_maxWPNameLength);
998 oNMEA0183.Wpl.Write(snt);
999 }
else if (g_GPS_Ident == _T(
"FurunoGP3X")) {
1000 oNMEA0183.TalkerID = _T (
"PFEC," );
1002 if (prp->m_lat < 0.)
1003 oNMEA0183.GPwpl.Position.Latitude.Set(-prp->m_lat, _T (
"S" ));
1005 oNMEA0183.GPwpl.Position.Latitude.Set(prp->m_lat, _T (
"N" ));
1007 if (prp->m_lon < 0.)
1008 oNMEA0183.GPwpl.Position.Longitude.Set(-prp->m_lon, _T (
"W" ));
1010 oNMEA0183.GPwpl.Position.Longitude.Set(prp->m_lon, _T (
"E" ));
1012 wxString name = prp->GetName();
1013 name += _T(
"000000");
1014 name.Truncate(g_maxWPNameLength);
1016 oNMEA0183.GPwpl.To = name;
1018 oNMEA0183.GPwpl.Write(snt);
1021 auto msg_out = std::make_shared<Nmea0183Msg>(std::string(
"ECWPL"),
1022 snt.Sentence.ToStdString(),
1024 drv_n0183->SendMessage(msg_out, address);
1028 wxString msg(_T(
"-->GPS Port:"));
1030 msg += _T(
" Sentence: ");
1031 msg += snt.Sentence;
1035 if (g_GPS_Ident == _T(
"FurunoGP3X")) {
1037 term.Printf(_T(
"$PFEC,GPxfr,CTL,E%c%c"), 0x0d, 0x0a);
1042 wxString msg(_T(
"-->GPS Port:"));
1044 msg += _T(
" Sentence: ");
1060 registry.Deactivate(driver);
1066 if (b_restoreStream) {
1068 MakeCommDriver(¶ms_save);