27 #include <wx/wxprec.h>
34 #include <wx/string.h>
35 #include <wx/tokenzr.h>
36 #include <wx/fileconf.h>
38 #include "model/comm_ais.h"
39 #include "model/comm_appmsg_bus.h"
40 #include "model/comm_bridge.h"
41 #include "model/comm_drv_registry.h"
42 #include "model/comm_navmsg_bus.h"
43 #include "model/comm_vars.h"
44 #include "model/config_vars.h"
45 #include "model/idents.h"
46 #include "model/ocpn_types.h"
47 #include "model/own_ship.h"
48 #include "model/multiplexer.h"
72 #define N_ACTIVE_LOG_WATCHDOG 300
76 bool debug_priority = 0;
94 static void SendBasicNavdata(
int vflag) {
95 auto msg = std::make_shared<BasicNavDataMsg>(
96 gLat, gLon, gSog, gCog, gVar, gHdt, vflag, wxDateTime::Now().GetTicks());
97 AppMsgBus::GetInstance().
Notify(std::move(msg));
101 static inline double GeodesicRadToDeg(
double rads) {
102 return rads * 180.0 / M_PI;
105 static inline double MS2KNOTS(
double ms) {
106 return ms * 1.9438444924406;
112 EVT_TIMER(WATCHDOG_TIMER, CommBridge::OnWatchdogTimer)
117 CommBridge::~CommBridge() {}
119 bool CommBridge::Initialize() {
121 InitializePriorityContainers();
125 PresetPriorityContainers();
130 m_watchdog_timer.SetOwner(
this, WATCHDOG_TIMER);
131 m_watchdog_timer.Start(1000, wxTIMER_CONTINUOUS);
132 n_LogWatchdogPeriod = 3600;
139 driver_change_listener.
Listen(
140 CommDriverRegistry::GetInstance().evt_driverlist_change.key,
this,
142 Bind(EVT_DRIVER_CHANGE, [&](wxCommandEvent ev) {
143 OnDriverStateChange(); });
149 void CommBridge::PresetWatchdogs() {
150 m_watchdogs.position_watchdog = 20;
151 m_watchdogs.velocity_watchdog = 20;
152 m_watchdogs.variation_watchdog = 20;
153 m_watchdogs.heading_watchdog = 20;
154 m_watchdogs.satellite_watchdog = 20;
157 void CommBridge::SelectNextLowerPriority(
const std::unordered_map<std::string, int> &map,
161 for (
auto it = map.begin(); it != map.end(); it++) {
162 if (it->second > pc.active_priority){
163 best_prio = wxMin(best_prio, it->second);
167 pc.active_priority = best_prio;
168 pc.active_source.clear();
169 pc.active_identifier.clear();
173 void CommBridge::OnWatchdogTimer(wxTimerEvent& event) {
175 m_watchdogs.position_watchdog--;
176 if (m_watchdogs.position_watchdog <= 0) {
177 if (m_watchdogs.position_watchdog % 5 == 0) {
179 auto msg = std::make_shared<GPSWatchdogMsg>(GPSWatchdogMsg::WDSource::position,
180 m_watchdogs.position_watchdog);
181 auto& msgbus = AppMsgBus::GetInstance();
182 msgbus.Notify(std::move(msg));
184 if (m_watchdogs.position_watchdog % n_LogWatchdogPeriod == 0) {
186 logmsg.Printf(_T(
" ***GPS Watchdog timeout at Lat:%g Lon: %g"), gLat,
188 wxLogMessage(logmsg);
199 SelectNextLowerPriority(priority_map_position, active_priority_position);
203 m_watchdogs.velocity_watchdog--;
204 if (m_watchdogs.velocity_watchdog <= 0) {
207 if (g_nNMEADebug && (m_watchdogs.velocity_watchdog == 0))
208 wxLogMessage(_T(
" ***Velocity Watchdog timeout..."));
209 if (m_watchdogs.velocity_watchdog % 5 == 0) {
211 auto msg = std::make_shared<GPSWatchdogMsg>(GPSWatchdogMsg::WDSource::velocity,
212 m_watchdogs.velocity_watchdog);
213 auto& msgbus = AppMsgBus::GetInstance();
214 msgbus.Notify(std::move(msg));
218 SelectNextLowerPriority(priority_map_velocity, active_priority_velocity);
222 m_watchdogs.heading_watchdog--;
223 if (m_watchdogs.heading_watchdog <= 0) {
225 if (g_nNMEADebug && (m_watchdogs.heading_watchdog == 0))
226 wxLogMessage(_T(
" ***HDT Watchdog timeout..."));
230 SelectNextLowerPriority(priority_map_heading, active_priority_heading);
234 m_watchdogs.variation_watchdog--;
235 if (m_watchdogs.variation_watchdog <= 0) {
237 if (g_nNMEADebug && (m_watchdogs.variation_watchdog == 0))
238 wxLogMessage(_T(
" ***VAR Watchdog timeout..."));
242 SelectNextLowerPriority(priority_map_variation, active_priority_variation);
246 m_watchdogs.satellite_watchdog--;
247 if (m_watchdogs.satellite_watchdog <= 0) {
251 if (g_nNMEADebug && (m_watchdogs.satellite_watchdog == 0))
252 wxLogMessage(_T(
" ***SAT Watchdog timeout..."));
256 SelectNextLowerPriority(priority_map_satellites, active_priority_satellites);
260 void CommBridge::MakeHDTFromHDM() {
264 if (!std::isnan(gHdm)) {
267 if (std::isnan(gVar) && (g_UserVar != 0.0)) gVar = g_UserVar;
269 if (!std::isnan(gHdt)) {
272 else if (gHdt >= 360)
275 m_watchdogs.heading_watchdog = gps_watchdog_timeout_ticks;
280 void CommBridge::InitCommListeners() {
282 auto& msgbus = NavMsgBus::GetInstance();
286 Nmea2000Msg n2k_msg_129029(
static_cast<uint64_t
>(129029));
287 listener_N2K_129029.
Listen(n2k_msg_129029,
this, EVT_N2K_129029);
290 HandleN2K_129029(UnpackEvtPointer<Nmea2000Msg>(ev));
295 Nmea2000Msg n2k_msg_129025(
static_cast<uint64_t
>(129025));
296 listener_N2K_129025.
Listen(n2k_msg_129025,
this, EVT_N2K_129025);
298 HandleN2K_129025(UnpackEvtPointer<Nmea2000Msg>(ev));
303 Nmea2000Msg n2k_msg_129026(
static_cast<uint64_t
>(129026));
304 listener_N2K_129026.
Listen(n2k_msg_129026,
this, EVT_N2K_129026);
306 HandleN2K_129026(UnpackEvtPointer<Nmea2000Msg>(ev));
311 Nmea2000Msg n2k_msg_127250(
static_cast<uint64_t
>(127250));
312 listener_N2K_127250.
Listen(n2k_msg_127250,
this, EVT_N2K_127250);
314 HandleN2K_127250(UnpackEvtPointer<Nmea2000Msg>(ev));
319 Nmea2000Msg n2k_msg_129540(
static_cast<uint64_t
>(129540));
320 listener_N2K_129540.
Listen(n2k_msg_129540,
this, EVT_N2K_129540);
322 HandleN2K_129540(UnpackEvtPointer<Nmea2000Msg>(ev));
329 listener_N0183_RMC.
Listen(n0183_msg_RMC,
this, EVT_N0183_RMC);
332 HandleN0183_RMC(UnpackEvtPointer<Nmea0183Msg>(ev));
337 listener_N0183_HDT.
Listen(n0183_msg_HDT,
this, EVT_N0183_HDT);
340 HandleN0183_HDT(UnpackEvtPointer<Nmea0183Msg>(ev));
345 listener_N0183_HDG.
Listen(n0183_msg_HDG,
this, EVT_N0183_HDG);
348 HandleN0183_HDG(UnpackEvtPointer<Nmea0183Msg>(ev));
353 listener_N0183_HDM.
Listen(n0183_msg_HDM,
this, EVT_N0183_HDM);
356 HandleN0183_HDM(UnpackEvtPointer<Nmea0183Msg>(ev));
361 listener_N0183_VTG.
Listen(n0183_msg_VTG,
this, EVT_N0183_VTG);
364 HandleN0183_VTG(UnpackEvtPointer<Nmea0183Msg>(ev));
369 listener_N0183_GSV.
Listen(n0183_msg_GSV,
this, EVT_N0183_GSV);
372 HandleN0183_GSV(UnpackEvtPointer<Nmea0183Msg>(ev));
377 listener_N0183_GGA.
Listen(n0183_msg_GGA,
this, EVT_N0183_GGA);
380 HandleN0183_GGA(UnpackEvtPointer<Nmea0183Msg>(ev));
385 listener_N0183_GLL.
Listen(n0183_msg_GLL,
this, EVT_N0183_GLL);
388 HandleN0183_GLL(UnpackEvtPointer<Nmea0183Msg>(ev));
393 listener_N0183_AIVDO.
Listen(n0183_msg_AIVDO,
this, EVT_N0183_AIVDO);
396 HandleN0183_AIVDO(UnpackEvtPointer<Nmea0183Msg>(ev));
401 listener_SignalK.
Listen(sk_msg,
this, EVT_SIGNALK);
404 HandleSignalK(UnpackEvtPointer<SignalkMsg>(ev));
409 void CommBridge::OnDriverStateChange(){
412 PresetPriorityContainers();
416 std::string CommBridge::GetPriorityMap(std::unordered_map<std::string, int> &map){
418 #define MAX_SOURCES 10
419 std::string sa[MAX_SOURCES];
422 for (
auto& it: map) {
423 if ((it.second >= 0) && (it.second < MAX_SOURCES))
424 sa[it.second] = it.first;
428 for (
int i=0 ; i < MAX_SOURCES ; i++){
440 std::vector<std::string> CommBridge::GetPriorityMaps(){
442 std::vector<std::string> result;
444 result.push_back(GetPriorityMap(priority_map_position));
445 result.push_back(GetPriorityMap(priority_map_velocity));
446 result.push_back(GetPriorityMap(priority_map_heading));
447 result.push_back(GetPriorityMap(priority_map_variation));
448 result.push_back(GetPriorityMap(priority_map_satellites));
454 void CommBridge::ApplyPriorityMap(std::unordered_map<std::string, int>& priority_map, wxString &new_prio,
int category){
455 priority_map.clear();
456 wxStringTokenizer tk(new_prio,
"|");
458 while (tk.HasMoreTokens()) {
459 wxString entry = tk.GetNextToken();
460 std::string s_entry(entry.c_str());
461 priority_map[s_entry] = index;
467 void CommBridge::ApplyPriorityMaps(std::vector<std::string> new_maps){
469 wxString new_prio_string;
471 new_prio_string = wxString( new_maps[0].c_str());
472 ApplyPriorityMap(priority_map_position, new_prio_string, 0);
474 new_prio_string = wxString( new_maps[1].c_str());
475 ApplyPriorityMap(priority_map_velocity, new_prio_string, 1);
477 new_prio_string = wxString( new_maps[2].c_str());
478 ApplyPriorityMap(priority_map_heading, new_prio_string, 2);
480 new_prio_string = wxString( new_maps[3].c_str());
481 ApplyPriorityMap(priority_map_variation, new_prio_string, 3);
483 new_prio_string = wxString( new_maps[4].c_str());
484 ApplyPriorityMap(priority_map_satellites, new_prio_string, 4);
488 const std::unordered_map<std::string, int> &priority_map){
492 for (
auto& it: priority_map) {
497 wxString this_key(key0.c_str());
498 wxStringTokenizer tkz(this_key, _T(
";"));
499 wxString wxs_this_source = tkz.GetNextToken();
500 std::string source = wxs_this_source.ToStdString();
501 wxString wxs_this_identifier = tkz.GetNextToken();
502 std::string this_identifier = wxs_this_identifier.ToStdString();
504 wxStringTokenizer tka(wxs_this_source, _T(
":"));
506 int source_address = atoi(tka.GetNextToken().ToStdString().c_str());
508 pc.active_priority = 0;
509 pc.active_source = source;
510 pc.active_identifier = this_identifier;
511 pc.active_source_address = source_address;
515 void CommBridge::PresetPriorityContainers(){
516 PresetPriorityContainer(active_priority_position, priority_map_position);
517 PresetPriorityContainer(active_priority_velocity, priority_map_velocity);
518 PresetPriorityContainer(active_priority_heading, priority_map_heading);
519 PresetPriorityContainer(active_priority_variation, priority_map_variation);
520 PresetPriorityContainer(active_priority_satellites, priority_map_satellites);
524 bool CommBridge::HandleN2K_129029(std::shared_ptr<const Nmea2000Msg> n2k_msg) {
526 std::vector<unsigned char> v = n2k_msg->payload;
530 unsigned char *c = (
unsigned char *)&pgn;
536 ClearNavData(temp_data);
538 if (!m_decoder.DecodePGN129029(v, temp_data))
542 if (!N2kIsNA(temp_data.gLat) && !N2kIsNA(temp_data.gLon)){
543 if (EvalPriority(n2k_msg, active_priority_position, priority_map_position)) {
544 gLat = temp_data.gLat;
545 gLon = temp_data.gLon;
546 valid_flag += POS_UPDATE;
547 valid_flag += POS_VALID;
548 m_watchdogs.position_watchdog = gps_watchdog_timeout_ticks;
549 n_LogWatchdogPeriod = N_ACTIVE_LOG_WATCHDOG;
553 if (temp_data.n_satellites >= 0){
554 if (EvalPriority(n2k_msg, active_priority_satellites, priority_map_satellites)) {
555 g_SatsInView = temp_data.n_satellites;
557 m_watchdogs.satellite_watchdog = sat_watchdog_timeout_ticks;
561 SendBasicNavdata(valid_flag);
565 bool CommBridge::HandleN2K_129025(std::shared_ptr<const Nmea2000Msg> n2k_msg) {
567 std::vector<unsigned char> v = n2k_msg->payload;
570 ClearNavData(temp_data);
572 if (!m_decoder.DecodePGN129025(v, temp_data))
576 if (!N2kIsNA(temp_data.gLat) && !N2kIsNA(temp_data.gLon)){
577 if (EvalPriority(n2k_msg, active_priority_position, priority_map_position)) {
578 gLat = temp_data.gLat;
579 gLon = temp_data.gLon;
580 valid_flag += POS_UPDATE;
581 valid_flag += POS_VALID;
582 m_watchdogs.position_watchdog = gps_watchdog_timeout_ticks;
583 n_LogWatchdogPeriod = N_ACTIVE_LOG_WATCHDOG;
590 SendBasicNavdata(valid_flag);
594 bool CommBridge::HandleN2K_129026(std::shared_ptr<const Nmea2000Msg> n2k_msg) {
596 std::vector<unsigned char> v = n2k_msg->payload;
599 ClearNavData(temp_data);
601 if (!m_decoder.DecodePGN129026(v, temp_data))
605 if (!N2kIsNA(temp_data.gSog)){
606 if (EvalPriority(n2k_msg, active_priority_velocity, priority_map_velocity)) {
607 gSog = MS2KNOTS(temp_data.gSog);
608 valid_flag += SOG_UPDATE;
610 if (N2kIsNA(temp_data.gCog))
613 gCog = GeodesicRadToDeg(temp_data.gCog);
614 valid_flag += COG_UPDATE;
615 m_watchdogs.velocity_watchdog = gps_watchdog_timeout_ticks;
621 SendBasicNavdata(valid_flag);
625 bool CommBridge::HandleN2K_127250(std::shared_ptr<const Nmea2000Msg> n2k_msg) {
627 std::vector<unsigned char> v = n2k_msg->payload;
630 ClearNavData(temp_data);
632 if (!m_decoder.DecodePGN127250(v, temp_data))
636 if (!N2kIsNA(temp_data.gVar)){
637 if (EvalPriority(n2k_msg, active_priority_variation, priority_map_variation)) {
638 gVar = GeodesicRadToDeg(temp_data.gVar);
639 valid_flag += VAR_UPDATE;
640 m_watchdogs.variation_watchdog = gps_watchdog_timeout_ticks;
644 if (!N2kIsNA(temp_data.gHdt)){
645 if (EvalPriority(n2k_msg, active_priority_heading, priority_map_heading)) {
646 gHdt = GeodesicRadToDeg(temp_data.gHdt);
647 valid_flag += HDT_UPDATE;
648 m_watchdogs.heading_watchdog = gps_watchdog_timeout_ticks;
652 if (!N2kIsNA(temp_data.gHdm)){
653 gHdm = GeodesicRadToDeg(temp_data.gHdm);
654 if (EvalPriority(n2k_msg, active_priority_heading, priority_map_heading)) {
656 valid_flag += HDT_UPDATE;
657 if(!std::isnan(gHdt))
658 m_watchdogs.heading_watchdog = gps_watchdog_timeout_ticks;
662 SendBasicNavdata(valid_flag);
666 bool CommBridge::HandleN2K_129540(std::shared_ptr<const Nmea2000Msg> n2k_msg) {
668 std::vector<unsigned char> v = n2k_msg->payload;
671 ClearNavData(temp_data);
673 if (!m_decoder.DecodePGN129540(v, temp_data))
677 if (temp_data.n_satellites >= 0){
678 if (EvalPriority(n2k_msg, active_priority_satellites, priority_map_satellites)) {
679 g_SatsInView = temp_data.n_satellites;
681 m_watchdogs.satellite_watchdog = sat_watchdog_timeout_ticks;
688 bool CommBridge::HandleN0183_RMC(std::shared_ptr<const Nmea0183Msg> n0183_msg) {
689 std::string str = n0183_msg->payload;
692 ClearNavData(temp_data);
695 if (!m_decoder.DecodeRMC(str, temp_data))
699 if (EvalPriority(n0183_msg, active_priority_position, priority_map_position)) {
701 gLat = temp_data.gLat;
702 gLon = temp_data.gLon;
703 valid_flag += POS_VALID;
704 m_watchdogs.position_watchdog = gps_watchdog_timeout_ticks;
705 n_LogWatchdogPeriod = N_ACTIVE_LOG_WATCHDOG;
707 valid_flag += POS_UPDATE;
710 if (EvalPriority(n0183_msg, active_priority_velocity, priority_map_velocity)) {
712 gSog = temp_data.gSog;
713 valid_flag += SOG_UPDATE;
714 gCog = temp_data.gCog;
715 valid_flag += COG_UPDATE;
716 m_watchdogs.velocity_watchdog = gps_watchdog_timeout_ticks;
720 if (!std::isnan(temp_data.gVar)){
721 if (EvalPriority(n0183_msg, active_priority_variation, priority_map_variation)) {
723 gVar = temp_data.gVar;
724 valid_flag += VAR_UPDATE;
725 m_watchdogs.variation_watchdog = gps_watchdog_timeout_ticks;
730 SendBasicNavdata(valid_flag);
734 bool CommBridge::HandleN0183_HDT(std::shared_ptr<const Nmea0183Msg> n0183_msg) {
735 std::string str = n0183_msg->payload;
737 ClearNavData(temp_data);
739 if (!m_decoder.DecodeHDT(str, temp_data))
743 if (EvalPriority(n0183_msg, active_priority_heading, priority_map_heading)) {
744 gHdt = temp_data.gHdt;
745 valid_flag += HDT_UPDATE;
746 m_watchdogs.heading_watchdog = gps_watchdog_timeout_ticks;
750 SendBasicNavdata(valid_flag);
754 bool CommBridge::HandleN0183_HDG(std::shared_ptr<const Nmea0183Msg> n0183_msg) {
755 std::string str = n0183_msg->payload;
757 ClearNavData(temp_data);
759 if (!m_decoder.DecodeHDG(str, temp_data))
return false;
764 if (EvalPriority(n0183_msg, active_priority_heading, priority_map_heading)) {
765 gHdm = temp_data.gHdm;
766 m_watchdogs.heading_watchdog = gps_watchdog_timeout_ticks;
770 if (!std::isnan(temp_data.gVar)){
771 if (EvalPriority(n0183_msg, active_priority_variation, priority_map_variation)) {
772 gVar = temp_data.gVar;
773 valid_flag += VAR_UPDATE;
774 m_watchdogs.variation_watchdog = gps_watchdog_timeout_ticks;
781 SendBasicNavdata(valid_flag);
785 bool CommBridge::HandleN0183_HDM(std::shared_ptr<const Nmea0183Msg> n0183_msg) {
786 std::string str = n0183_msg->payload;
788 ClearNavData(temp_data);
790 if (!m_decoder.DecodeHDM(str, temp_data))
return false;
794 if (EvalPriority(n0183_msg, active_priority_heading, priority_map_heading)) {
795 gHdm = temp_data.gHdm;
797 valid_flag += HDT_UPDATE;
798 m_watchdogs.heading_watchdog = gps_watchdog_timeout_ticks;
801 SendBasicNavdata(valid_flag);
805 bool CommBridge::HandleN0183_VTG(std::shared_ptr<const Nmea0183Msg> n0183_msg) {
806 std::string str = n0183_msg->payload;
808 ClearNavData(temp_data);
810 if (!m_decoder.DecodeVTG(str, temp_data))
return false;
814 if (EvalPriority(n0183_msg, active_priority_velocity, priority_map_velocity)) {
815 gSog = temp_data.gSog;
816 valid_flag += SOG_UPDATE;
817 gCog = temp_data.gCog;
818 valid_flag += COG_UPDATE;
819 m_watchdogs.velocity_watchdog = gps_watchdog_timeout_ticks;
822 SendBasicNavdata(valid_flag);
826 bool CommBridge::HandleN0183_GSV(std::shared_ptr<const Nmea0183Msg> n0183_msg) {
827 std::string str = n0183_msg->payload;
829 ClearNavData(temp_data);
831 if (!m_decoder.DecodeGSV(str, temp_data))
return false;
835 if (EvalPriority(n0183_msg, active_priority_satellites, priority_map_satellites)) {
836 if (temp_data.n_satellites >= 0){
837 g_SatsInView = temp_data.n_satellites;
840 m_watchdogs.satellite_watchdog = sat_watchdog_timeout_ticks;
844 SendBasicNavdata(valid_flag);
848 bool CommBridge::HandleN0183_GGA(std::shared_ptr<const Nmea0183Msg> n0183_msg) {
849 std::string str = n0183_msg->payload;
851 ClearNavData(temp_data);
854 if (!m_decoder.DecodeGGA(str, temp_data))
859 if (EvalPriority(n0183_msg, active_priority_position, priority_map_position)) {
861 gLat = temp_data.gLat;
862 gLon = temp_data.gLon;
863 valid_flag += POS_VALID;
864 m_watchdogs.position_watchdog = gps_watchdog_timeout_ticks;
865 n_LogWatchdogPeriod = N_ACTIVE_LOG_WATCHDOG;
867 valid_flag += POS_UPDATE;
870 if (EvalPriority(n0183_msg, active_priority_satellites, priority_map_satellites)) {
872 if (temp_data.n_satellites >= 0) {
873 g_SatsInView = temp_data.n_satellites;
876 m_watchdogs.satellite_watchdog = sat_watchdog_timeout_ticks;
881 SendBasicNavdata(valid_flag);
885 bool CommBridge::HandleN0183_GLL(std::shared_ptr<const Nmea0183Msg> n0183_msg) {
886 std::string str = n0183_msg->payload;
888 ClearNavData(temp_data);
891 if (!m_decoder.DecodeGLL(str, temp_data))
896 if (EvalPriority(n0183_msg, active_priority_position, priority_map_position)) {
898 gLat = temp_data.gLat;
899 gLon = temp_data.gLon;
900 valid_flag += POS_VALID;
901 m_watchdogs.position_watchdog = gps_watchdog_timeout_ticks;
902 n_LogWatchdogPeriod = N_ACTIVE_LOG_WATCHDOG;
904 valid_flag += POS_UPDATE;
907 SendBasicNavdata(valid_flag);
911 bool CommBridge::HandleN0183_AIVDO(
912 std::shared_ptr<const Nmea0183Msg> n0183_msg) {
913 std::string str = n0183_msg->payload;
916 wxString sentence(str.c_str());
920 AisError nerr = AIS_GENERIC_ERROR;
921 nerr = DecodeSingleVDO(sentence, &gpd);
923 if (nerr == AIS_NoError) {
925 if (!std::isnan(gpd.kLat) && !std::isnan(gpd.kLon)){
926 if (EvalPriority(n0183_msg, active_priority_position, priority_map_position)) {
929 valid_flag += POS_UPDATE;
930 valid_flag += POS_VALID;
931 m_watchdogs.position_watchdog = gps_watchdog_timeout_ticks;
932 n_LogWatchdogPeriod = N_ACTIVE_LOG_WATCHDOG;
936 if (!std::isnan(gpd.kCog) && !std::isnan(gpd.kSog)){
937 if (EvalPriority(n0183_msg, active_priority_velocity, priority_map_velocity)) {
939 valid_flag += SOG_UPDATE;
941 valid_flag += COG_UPDATE;
942 m_watchdogs.velocity_watchdog = gps_watchdog_timeout_ticks;
946 if (!std::isnan(gpd.kHdt)) {
947 if (EvalPriority(n0183_msg, active_priority_heading, priority_map_heading)) {
949 valid_flag += HDT_UPDATE;
950 m_watchdogs.heading_watchdog = gps_watchdog_timeout_ticks;
954 SendBasicNavdata(valid_flag);
959 bool CommBridge::HandleSignalK(std::shared_ptr<const SignalkMsg> sK_msg){
960 std::string str = sK_msg->raw_message;
963 if (sK_msg->context_self != sK_msg->context)
966 g_ownshipMMSI_SK = sK_msg->context_self;
969 ClearNavData(temp_data);
971 if (!m_decoder.DecodeSignalK(str, temp_data))
return false;
975 if (!std::isnan(temp_data.gLat) && !std::isnan(temp_data.gLon)){
976 if (EvalPriority(sK_msg, active_priority_position, priority_map_position)) {
977 gLat = temp_data.gLat;
978 gLon = temp_data.gLon;
979 valid_flag += POS_UPDATE;
980 valid_flag += POS_VALID;
981 m_watchdogs.position_watchdog = gps_watchdog_timeout_ticks;
982 n_LogWatchdogPeriod = N_ACTIVE_LOG_WATCHDOG;
986 if (!std::isnan(temp_data.gSog)){
987 if (EvalPriority(sK_msg, active_priority_velocity, priority_map_velocity)) {
988 gSog = temp_data.gSog;
989 valid_flag += SOG_UPDATE;
990 if((gSog > 0.05) && !std::isnan(temp_data.gCog)){
991 gCog = temp_data.gCog;
992 valid_flag += COG_UPDATE;
994 m_watchdogs.velocity_watchdog = gps_watchdog_timeout_ticks;
998 if (!std::isnan(temp_data.gHdt)){
999 if (EvalPriority(sK_msg, active_priority_heading, priority_map_heading)) {
1000 gHdt = temp_data.gHdt;
1001 valid_flag += HDT_UPDATE;
1002 m_watchdogs.heading_watchdog = gps_watchdog_timeout_ticks;
1006 if (!std::isnan(temp_data.gHdm)){
1007 if (EvalPriority(sK_msg, active_priority_heading, priority_map_heading)) {
1008 gHdm = temp_data.gHdm;
1010 valid_flag += HDT_UPDATE;
1011 m_watchdogs.heading_watchdog = gps_watchdog_timeout_ticks;
1015 if (!std::isnan(temp_data.gVar)){
1016 if (EvalPriority(sK_msg, active_priority_variation, priority_map_variation)) {
1017 gVar = temp_data.gVar;
1018 valid_flag += VAR_UPDATE;
1019 m_watchdogs.variation_watchdog = gps_watchdog_timeout_ticks;
1023 bool sat_update =
false;
1024 if (temp_data.n_satellites > 0){
1025 if (EvalPriority(sK_msg, active_priority_satellites, priority_map_satellites)) {
1026 g_SatsInView = temp_data.n_satellites;
1029 m_watchdogs.satellite_watchdog = sat_watchdog_timeout_ticks;
1033 if (g_pMUX && g_pMUX->IsLogActive()) {
1034 std::string logmsg =
"Self: ";
1035 std::string content;
1036 if (valid_flag & POS_UPDATE) content +=
"POS;";
1037 if (valid_flag & POS_VALID) content +=
"POS_Valid;";
1038 if (valid_flag & SOG_UPDATE) content +=
"SOG;";
1039 if (valid_flag & COG_UPDATE) content +=
"COG;";
1040 if (valid_flag & HDT_UPDATE) content +=
"HDT;";
1041 if (valid_flag & VAR_UPDATE) content +=
"VAR;";
1042 if (sat_update) content +=
"SAT;";
1044 if (content.empty())
1045 content =
"Not used by OCPN, maybe passed to plugins";
1048 std::string source = sK_msg->source->to_string();
1049 g_pMUX->LogInputMessage( logmsg, source,
false,
false);
1052 SendBasicNavdata(valid_flag);
1057 void CommBridge::InitializePriorityContainers(){
1058 active_priority_position.active_priority = 0;
1059 active_priority_velocity.active_priority = 0;
1060 active_priority_heading.active_priority = 0;
1061 active_priority_variation.active_priority = 0;
1062 active_priority_satellites.active_priority = 0;
1064 active_priority_position.active_source.clear();
1065 active_priority_velocity.active_source.clear();
1066 active_priority_heading.active_source.clear();
1067 active_priority_variation.active_source.clear();
1068 active_priority_satellites.active_source.clear();
1070 active_priority_position.active_identifier.clear();
1071 active_priority_velocity.active_identifier.clear();
1072 active_priority_heading.active_identifier.clear();
1073 active_priority_variation.active_identifier.clear();
1074 active_priority_satellites.active_identifier.clear();
1076 active_priority_position.pcclass =
"position";
1077 active_priority_velocity.pcclass =
"velocity";
1078 active_priority_heading.pcclass =
"heading";
1079 active_priority_variation.pcclass =
"variation";
1080 active_priority_satellites.pcclass =
"satellites";
1082 active_priority_position.active_source_address = -1;
1083 active_priority_velocity.active_source_address = -1;
1084 active_priority_heading.active_source_address = -1;
1085 active_priority_variation.active_source_address = -1;
1086 active_priority_satellites.active_source_address = -1;
1088 active_priority_void.active_priority = -1;
1092 void CommBridge::ClearPriorityMaps(){
1093 priority_map_position.clear();
1094 priority_map_velocity.clear();
1095 priority_map_heading.clear();
1096 priority_map_variation.clear();
1097 priority_map_satellites.clear();
1100 PriorityContainer& CommBridge::GetPriorityContainer(
const std::string category){
1101 if (!category.compare(
"position"))
1102 return active_priority_position;
1103 else if (!category.compare(
"velocity"))
1104 return active_priority_velocity;
1105 else if (!category.compare(
"heading"))
1106 return active_priority_heading;
1107 else if (!category.compare(
"variation"))
1108 return active_priority_variation;
1109 else if (!category.compare(
"satellites"))
1110 return active_priority_satellites;
1112 return active_priority_void;
1115 void CommBridge::UpdateAndApplyMaps(std::vector<std::string> new_maps){
1116 ApplyPriorityMaps(new_maps);
1118 PresetPriorityContainers();
1122 bool CommBridge::LoadConfig(
void )
1124 if( TheBaseConfig() ) {
1125 TheBaseConfig()->SetPath(
"/Settings/CommPriority");
1127 std::vector<std::string> new_maps;
1129 wxString pri_string;
1131 TheBaseConfig()->Read(
"PriorityPosition", &pri_string );
1132 s_prio = std::string(pri_string.c_str());
1133 new_maps.push_back(s_prio);
1135 TheBaseConfig()->Read(
"PriorityVelocity", &pri_string );
1136 s_prio = std::string(pri_string.c_str());
1137 new_maps.push_back(s_prio);
1139 TheBaseConfig()->Read(
"PriorityHeading", &pri_string );
1140 s_prio = std::string(pri_string.c_str());
1141 new_maps.push_back(s_prio);
1143 TheBaseConfig()->Read(
"PriorityVariation", &pri_string );
1144 s_prio = std::string(pri_string.c_str());
1145 new_maps.push_back(s_prio);
1147 TheBaseConfig()->Read(
"PrioritySatellites", &pri_string );
1148 s_prio = std::string(pri_string.c_str());
1149 new_maps.push_back(s_prio);
1151 ApplyPriorityMaps(new_maps);
1156 bool CommBridge::SaveConfig(
void )
1158 if( TheBaseConfig() ) {
1159 TheBaseConfig()->SetPath(
"/Settings/CommPriority");
1161 wxString pri_string;
1162 pri_string = wxString(GetPriorityMap(priority_map_position).c_str());
1163 TheBaseConfig()->Write(
"PriorityPosition", pri_string );
1165 pri_string = wxString(GetPriorityMap(priority_map_velocity).c_str());
1166 TheBaseConfig()->Write(
"PriorityVelocity", pri_string );
1168 pri_string = wxString(GetPriorityMap(priority_map_heading).c_str());
1169 TheBaseConfig()->Write(
"PriorityHeading", pri_string );
1171 pri_string = wxString(GetPriorityMap(priority_map_variation).c_str());
1172 TheBaseConfig()->Write(
"PriorityVariation", pri_string );
1174 pri_string = wxString(GetPriorityMap(priority_map_satellites).c_str());
1175 TheBaseConfig()->Write(
"PrioritySatellites", pri_string );
1182 std::string CommBridge::GetPriorityKey(std::shared_ptr <const NavMsg> msg){
1183 std::string source = msg->source->to_string();
1184 std::string listener_key = msg->key();
1187 std::string this_identifier;
1188 std::string this_address(
"0");
1189 if(msg->bus == NavAddr::Bus::N0183){
1190 auto msg_0183 = std::dynamic_pointer_cast<const Nmea0183Msg>(msg);
1192 this_identifier = msg_0183->talker;
1193 this_identifier += msg_0183->type;
1196 else if(msg->bus == NavAddr::Bus::N2000){
1197 auto msg_n2k = std::dynamic_pointer_cast<const Nmea2000Msg>(msg);
1199 this_identifier = msg_n2k->PGN.to_string();
1200 unsigned char n_source = msg_n2k->payload.at(7);
1202 sprintf(ss,
"%d",n_source);
1203 this_address = std::string(ss);
1206 else if(msg->bus == NavAddr::Bus::Signalk){
1207 auto msg_sk = std::dynamic_pointer_cast<const SignalkMsg>(msg);
1209 auto addr_sk = std::static_pointer_cast<const NavAddrSignalK>(msg->source);
1210 source = addr_sk->to_string();
1211 this_identifier =
"signalK";
1212 this_address = msg->source->iface;
1217 return source +
":" + this_address +
";" + this_identifier;
1221 bool CommBridge::EvalPriority(std::shared_ptr <const NavMsg> msg,
1223 std::unordered_map<std::string, int>& priority_map) {
1225 std::string this_key = GetPriorityKey(msg);
1226 if (debug_priority) printf(
"This Key: %s\n", this_key.c_str());
1229 wxStringTokenizer tkz(this_key, _T(
";"));
1230 wxString wxs_this_source = tkz.GetNextToken();
1231 std::string source = wxs_this_source.ToStdString();
1232 wxString wxs_this_identifier = tkz.GetNextToken();
1233 std::string this_identifier = wxs_this_identifier.ToStdString();
1235 wxStringTokenizer tka(wxs_this_source, _T(
":"));
1237 int source_address = atoi(tka.GetNextToken().ToStdString().c_str());
1242 auto it = priority_map.find(this_key);
1243 if (it == priority_map.end()) {
1245 priority_map[this_key] = 0;
1248 this_priority = priority_map[this_key];
1250 for (
auto it = priority_map.begin(); it != priority_map.end(); it++) {
1251 if (debug_priority) printf(
" priority_map: %s %d\n", it->first.c_str(), it->second);
1256 if (this_priority > active_priority.active_priority){
1257 if (debug_priority) printf(
" Drop low priority: %s %d %d \n", source.c_str(), this_priority,
1258 active_priority.active_priority);
1263 if (this_priority < active_priority.active_priority){
1264 active_priority.active_priority = this_priority;
1265 active_priority.active_source = source;
1266 active_priority.active_identifier = this_identifier;
1267 active_priority.active_source_address = source_address;
1269 if (debug_priority) printf(
" Restoring high priority: %s %d\n", source.c_str(), this_priority);
1277 if (active_priority.active_source.size()){
1279 if (debug_priority) printf(
"source: %s\n", source.c_str());
1280 if (debug_priority) printf(
"active_source: %s\n", active_priority.active_source.c_str());
1282 if (source.compare(active_priority.active_source) != 0){
1286 int lowest_priority = -10;
1287 for (
auto it = priority_map.begin(); it != priority_map.end(); it++) {
1288 if (it->second > lowest_priority)
1289 lowest_priority = it->second;
1292 priority_map[this_key] = lowest_priority + 1;
1293 if (debug_priority) printf(
" Lowering priority A: %s :%d\n", source.c_str(), priority_map[this_key]);
1302 if(msg->bus == NavAddr::Bus::N0183){
1303 auto msg_0183 = std::dynamic_pointer_cast<const Nmea0183Msg>(msg);
1305 if (active_priority.active_identifier.size()){
1307 if (debug_priority) printf(
"this_identifier: %s\n", this_identifier.c_str());
1308 if (debug_priority) printf(
"active_priority.active_identifier: %s\n", active_priority.active_identifier.c_str());
1310 if (this_identifier.compare(active_priority.active_identifier) != 0){
1313 if (priority_map[this_key] == active_priority.active_priority){
1314 int lowest_priority = -10;
1315 for (
auto it = priority_map.begin(); it != priority_map.end(); it++) {
1316 if (it->second > lowest_priority)
1317 lowest_priority = it->second;
1320 priority_map[this_key] = lowest_priority + 1;
1321 if (debug_priority) printf(
" Lowering priority B: %s :%d\n", source.c_str(), priority_map[this_key]);
1332 else if(msg->bus == NavAddr::Bus::N2000){
1333 auto msg_n2k = std::dynamic_pointer_cast<const Nmea2000Msg>(msg);
1335 if (active_priority.active_identifier.size()){
1336 if (this_identifier.compare(active_priority.active_identifier) != 0){
1339 if (priority_map[this_key] == active_priority.active_priority){
1340 int lowest_priority = -10;
1341 for (
auto it = priority_map.begin(); it != priority_map.end(); it++) {
1342 if (it->second > lowest_priority)
1343 lowest_priority = it->second;
1346 priority_map[this_key] = lowest_priority + 1;
1347 if (debug_priority) printf(
" Lowering priority: %s :%d\n", source.c_str(), priority_map[this_key]);
1358 active_priority.active_source = source;
1359 active_priority.active_identifier = this_identifier;
1360 active_priority.active_source_address = source_address;
1361 if (debug_priority) printf(
" Accepting high priority: %s %d\n", source.c_str(), this_priority);
void Notify(std::shared_ptr< const AppMsg > msg)
Send message to everyone listening to given message type.
A regular Nmea0183 message.
See: https://github.com/OpenCPN/OpenCPN/issues/2729#issuecomment-1179506343.
void Listen(const std::string &key, wxEvtHandler *listener, wxEventType evt)
Set object to send wxEventType ev to listener on changes in key.
Adds a std::shared<void> element to wxCommandEvent.
A parsed SignalK message over ipv4.
wxDEFINE_EVENT(REST_IO_EVT, ObservedEvt)
Event from IO thread to main.