35#include <wx/tokenzr.h>
36#include <wx/fileconf.h>
39#include "comm_appmsg_bus.h"
40#include "comm_bridge.h"
41#include "comm_drv_registry.h"
42#include "comm_navmsg_bus.h"
44#include "config_vars.h"
46#include "OCPNPlatform.h"
47#include "ocpn_types.h"
68wxDEFINE_EVENT(EVT_DRIVER_CHANGE, wxCommandEvent);
72bool debug_priority = 0;
90static void SendBasicNavdata() {
91 auto msg = std::make_shared<BasicNavDataMsg>(
92 gLat, gLon, gSog, gCog, gVar, gHdt, wxDateTime::Now().GetTicks());
93 AppMsgBus::GetInstance().
Notify(std::move(msg));
97static inline double GeodesicRadToDeg(
double rads) {
98 return rads * 180.0 / M_PI;
101static inline double MS2KNOTS(
double ms) {
102 return ms * 1.9438444924406;
108EVT_TIMER(WATCHDOG_TIMER, CommBridge::OnWatchdogTimer)
113CommBridge::~CommBridge() {}
115bool CommBridge::Initialize() {
117 InitializePriorityContainers();
121 PresetPriorityContainers();
126 m_watchdog_timer.SetOwner(
this, WATCHDOG_TIMER);
127 m_watchdog_timer.Start(1000, wxTIMER_CONTINUOUS);
133 driver_change_listener.
Listen(
134 CommDriverRegistry::GetInstance().evt_driverlist_change.key,
this,
136 Bind(EVT_DRIVER_CHANGE, [&](wxCommandEvent ev) {
137 OnDriverStateChange(); });
143void CommBridge::PresetWatchdogs() {
144 m_watchdogs.position_watchdog = 20;
145 m_watchdogs.velocity_watchdog = 20;
146 m_watchdogs.variation_watchdog = 20;
147 m_watchdogs.heading_watchdog = 20;
148 m_watchdogs.satellite_watchdog = 20;
151void CommBridge::SelectNextLowerPriority(
const std::unordered_map<std::string, int> &map,
155 for (
auto it = map.begin(); it != map.end(); it++) {
156 if (it->second > pc.active_priority){
157 best_prio = wxMin(best_prio, it->second);
161 pc.active_priority = best_prio;
162 pc.active_source.clear();
163 pc.active_identifier.clear();
167void CommBridge::OnWatchdogTimer(wxTimerEvent& event) {
169 m_watchdogs.position_watchdog--;
170 if (m_watchdogs.position_watchdog <= 0) {
171 if (m_watchdogs.position_watchdog % 5 == 0) {
173 auto msg = std::make_shared<GPSWatchdogMsg>(GPSWatchdogMsg::WDSource::position,
174 m_watchdogs.position_watchdog);
175 auto& msgbus = AppMsgBus::GetInstance();
176 msgbus.Notify(std::move(msg));
179 logmsg.Printf(_T(
" ***GPS Watchdog timeout at Lat:%g Lon: %g"), gLat,
181 wxLogMessage(logmsg);
191 SelectNextLowerPriority(priority_map_position, active_priority_position);
195 m_watchdogs.velocity_watchdog--;
196 if (m_watchdogs.velocity_watchdog <= 0) {
199 if (g_nNMEADebug && (m_watchdogs.velocity_watchdog == 0))
200 wxLogMessage(_T(
" ***Velocity Watchdog timeout..."));
201 if (m_watchdogs.velocity_watchdog % 5 == 0) {
203 auto msg = std::make_shared<GPSWatchdogMsg>(GPSWatchdogMsg::WDSource::velocity,
204 m_watchdogs.velocity_watchdog);
205 auto& msgbus = AppMsgBus::GetInstance();
206 msgbus.Notify(std::move(msg));
210 SelectNextLowerPriority(priority_map_velocity, active_priority_velocity);
214 m_watchdogs.heading_watchdog--;
215 if (m_watchdogs.heading_watchdog <= 0) {
217 if (g_nNMEADebug && (m_watchdogs.heading_watchdog == 0))
218 wxLogMessage(_T(
" ***HDT Watchdog timeout..."));
222 SelectNextLowerPriority(priority_map_heading, active_priority_heading);
226 m_watchdogs.variation_watchdog--;
227 if (m_watchdogs.variation_watchdog <= 0) {
229 if (g_nNMEADebug && (m_watchdogs.variation_watchdog == 0))
230 wxLogMessage(_T(
" ***VAR Watchdog timeout..."));
234 SelectNextLowerPriority(priority_map_variation, active_priority_variation);
238 m_watchdogs.satellite_watchdog--;
239 if (m_watchdogs.satellite_watchdog <= 0) {
243 if (g_nNMEADebug && (m_watchdogs.satellite_watchdog == 0))
244 wxLogMessage(_T(
" ***SAT Watchdog timeout..."));
248 SelectNextLowerPriority(priority_map_satellites, active_priority_satellites);
252void CommBridge::MakeHDTFromHDM() {
256 if (!std::isnan(gHdm)) {
259 if (std::isnan(gVar) && (g_UserVar != 0.0)) gVar = g_UserVar;
261 if (!std::isnan(gHdt)) {
264 else if (gHdt >= 360)
267 m_watchdogs.heading_watchdog = gps_watchdog_timeout_ticks;
272void CommBridge::InitCommListeners() {
274 auto& msgbus = NavMsgBus::GetInstance();
278 Nmea2000Msg n2k_msg_129029(
static_cast<uint64_t
>(129029));
279 listener_N2K_129029.
Listen(n2k_msg_129029,
this, EVT_N2K_129029);
282 HandleN2K_129029(UnpackEvtPointer<Nmea2000Msg>(ev));
287 Nmea2000Msg n2k_msg_129025(
static_cast<uint64_t
>(129025));
288 listener_N2K_129025.
Listen(n2k_msg_129025,
this, EVT_N2K_129025);
290 HandleN2K_129025(UnpackEvtPointer<Nmea2000Msg>(ev));
295 Nmea2000Msg n2k_msg_129026(
static_cast<uint64_t
>(129026));
296 listener_N2K_129026.
Listen(n2k_msg_129026,
this, EVT_N2K_129026);
298 HandleN2K_129026(UnpackEvtPointer<Nmea2000Msg>(ev));
303 Nmea2000Msg n2k_msg_127250(
static_cast<uint64_t
>(127250));
304 listener_N2K_127250.
Listen(n2k_msg_127250,
this, EVT_N2K_127250);
306 HandleN2K_127250(UnpackEvtPointer<Nmea2000Msg>(ev));
311 Nmea2000Msg n2k_msg_129540(
static_cast<uint64_t
>(129540));
312 listener_N2K_129540.
Listen(n2k_msg_129540,
this, EVT_N2K_129540);
314 HandleN2K_129540(UnpackEvtPointer<Nmea2000Msg>(ev));
321 listener_N0183_RMC.
Listen(n0183_msg_RMC,
this, EVT_N0183_RMC);
324 HandleN0183_RMC(UnpackEvtPointer<Nmea0183Msg>(ev));
329 listener_N0183_HDT.
Listen(n0183_msg_HDT,
this, EVT_N0183_HDT);
332 HandleN0183_HDT(UnpackEvtPointer<Nmea0183Msg>(ev));
337 listener_N0183_HDG.
Listen(n0183_msg_HDG,
this, EVT_N0183_HDG);
340 HandleN0183_HDG(UnpackEvtPointer<Nmea0183Msg>(ev));
345 listener_N0183_HDM.
Listen(n0183_msg_HDM,
this, EVT_N0183_HDM);
348 HandleN0183_HDM(UnpackEvtPointer<Nmea0183Msg>(ev));
353 listener_N0183_VTG.
Listen(n0183_msg_VTG,
this, EVT_N0183_VTG);
356 HandleN0183_VTG(UnpackEvtPointer<Nmea0183Msg>(ev));
361 listener_N0183_GSV.
Listen(n0183_msg_GSV,
this, EVT_N0183_GSV);
364 HandleN0183_GSV(UnpackEvtPointer<Nmea0183Msg>(ev));
369 listener_N0183_GGA.
Listen(n0183_msg_GGA,
this, EVT_N0183_GGA);
372 HandleN0183_GGA(UnpackEvtPointer<Nmea0183Msg>(ev));
377 listener_N0183_GLL.
Listen(n0183_msg_GLL,
this, EVT_N0183_GLL);
380 HandleN0183_GLL(UnpackEvtPointer<Nmea0183Msg>(ev));
385 listener_N0183_AIVDO.
Listen(n0183_msg_AIVDO,
this, EVT_N0183_AIVDO);
388 HandleN0183_AIVDO(UnpackEvtPointer<Nmea0183Msg>(ev));
393 listener_SignalK.
Listen(sk_msg,
this, EVT_SIGNALK);
396 HandleSignalK(UnpackEvtPointer<SignalkMsg>(ev));
401void CommBridge::OnDriverStateChange(){
404 PresetPriorityContainers();
408std::string CommBridge::GetPriorityMap(std::unordered_map<std::string, int> &map){
410 #define MAX_SOURCES 10
411 std::string sa[MAX_SOURCES];
414 for (
auto& it: map) {
415 if ((it.second >= 0) && (it.second < MAX_SOURCES))
416 sa[it.second] = it.first;
420 for (
int i=0 ; i < MAX_SOURCES ; i++){
432std::vector<std::string> CommBridge::GetPriorityMaps(){
434 std::vector<std::string> result;
436 result.push_back(GetPriorityMap(priority_map_position));
437 result.push_back(GetPriorityMap(priority_map_velocity));
438 result.push_back(GetPriorityMap(priority_map_heading));
439 result.push_back(GetPriorityMap(priority_map_variation));
440 result.push_back(GetPriorityMap(priority_map_satellites));
446void CommBridge::ApplyPriorityMap(std::unordered_map<std::string, int>& priority_map, wxString &new_prio,
int category){
447 priority_map.clear();
448 wxStringTokenizer tk(new_prio,
"|");
450 while (tk.HasMoreTokens()) {
451 wxString entry = tk.GetNextToken();
452 std::string s_entry(entry.c_str());
453 priority_map[s_entry] = index;
459void CommBridge::ApplyPriorityMaps(std::vector<std::string> new_maps){
461 wxString new_prio_string;
463 new_prio_string = wxString( new_maps[0].c_str());
464 ApplyPriorityMap(priority_map_position, new_prio_string, 0);
466 new_prio_string = wxString( new_maps[1].c_str());
467 ApplyPriorityMap(priority_map_velocity, new_prio_string, 1);
469 new_prio_string = wxString( new_maps[2].c_str());
470 ApplyPriorityMap(priority_map_heading, new_prio_string, 2);
472 new_prio_string = wxString( new_maps[3].c_str());
473 ApplyPriorityMap(priority_map_variation, new_prio_string, 3);
475 new_prio_string = wxString( new_maps[4].c_str());
476 ApplyPriorityMap(priority_map_satellites, new_prio_string, 4);
480 const std::unordered_map<std::string, int> &priority_map){
484 for (
auto& it: priority_map) {
489 wxString this_key(key0.c_str());
490 wxStringTokenizer tkz(this_key, _T(
";"));
491 wxString wxs_this_source = tkz.GetNextToken();
492 std::string source = wxs_this_source.ToStdString();
493 wxString wxs_this_identifier = tkz.GetNextToken();
494 std::string this_identifier = wxs_this_identifier.ToStdString();
496 wxStringTokenizer tka(wxs_this_source, _T(
":"));
498 int source_address = atoi(tka.GetNextToken().ToStdString().c_str());
500 pc.active_priority = 0;
501 pc.active_source = source;
502 pc.active_identifier = this_identifier;
503 pc.active_source_address = source_address;
507void CommBridge::PresetPriorityContainers(){
508 PresetPriorityContainer(active_priority_position, priority_map_position);
509 PresetPriorityContainer(active_priority_velocity, priority_map_velocity);
510 PresetPriorityContainer(active_priority_heading, priority_map_heading);
511 PresetPriorityContainer(active_priority_variation, priority_map_variation);
512 PresetPriorityContainer(active_priority_satellites, priority_map_satellites);
516bool CommBridge::HandleN2K_129029(std::shared_ptr<const Nmea2000Msg> n2k_msg) {
518 std::vector<unsigned char> v = n2k_msg->payload;
522 unsigned char *c = (
unsigned char *)&pgn;
528 ClearNavData(temp_data);
530 if (!m_decoder.DecodePGN129029(v, temp_data))
533 if (!N2kIsNA(temp_data.gLat) && !N2kIsNA(temp_data.gLon)){
534 if (EvalPriority(n2k_msg, active_priority_position, priority_map_position)) {
535 gLat = temp_data.gLat;
536 gLon = temp_data.gLon;
537 m_watchdogs.position_watchdog = gps_watchdog_timeout_ticks;
541 if (temp_data.n_satellites >= 0){
542 if (EvalPriority(n2k_msg, active_priority_satellites, priority_map_satellites)) {
543 g_SatsInView = temp_data.n_satellites;
545 m_watchdogs.satellite_watchdog = sat_watchdog_timeout_ticks;
553bool CommBridge::HandleN2K_129025(std::shared_ptr<const Nmea2000Msg> n2k_msg) {
555 std::vector<unsigned char> v = n2k_msg->payload;
558 ClearNavData(temp_data);
560 if (!m_decoder.DecodePGN129025(v, temp_data))
563 if (!N2kIsNA(temp_data.gLat) && !N2kIsNA(temp_data.gLon)){
564 if (EvalPriority(n2k_msg, active_priority_position, priority_map_position)) {
565 gLat = temp_data.gLat;
566 gLon = temp_data.gLon;
567 m_watchdogs.position_watchdog = gps_watchdog_timeout_ticks;
578bool CommBridge::HandleN2K_129026(std::shared_ptr<const Nmea2000Msg> n2k_msg) {
580 std::vector<unsigned char> v = n2k_msg->payload;
583 ClearNavData(temp_data);
585 if (!m_decoder.DecodePGN129026(v, temp_data))
588 if (!N2kIsNA(temp_data.gSog)){
589 if (EvalPriority(n2k_msg, active_priority_velocity, priority_map_velocity)) {
590 gSog = MS2KNOTS(temp_data.gSog);
591 if (N2kIsNA(temp_data.gCog))
594 gCog = GeodesicRadToDeg(temp_data.gCog);
595 m_watchdogs.velocity_watchdog = gps_watchdog_timeout_ticks;
605bool CommBridge::HandleN2K_127250(std::shared_ptr<const Nmea2000Msg> n2k_msg) {
607 std::vector<unsigned char> v = n2k_msg->payload;
610 ClearNavData(temp_data);
612 if (!m_decoder.DecodePGN127250(v, temp_data))
615 if (!N2kIsNA(temp_data.gVar)){
616 if (EvalPriority(n2k_msg, active_priority_variation, priority_map_variation)) {
617 gVar = GeodesicRadToDeg(temp_data.gVar);
618 m_watchdogs.variation_watchdog = gps_watchdog_timeout_ticks;
622 if (!N2kIsNA(temp_data.gHdt)){
623 if (EvalPriority(n2k_msg, active_priority_heading, priority_map_heading)) {
624 gHdt = GeodesicRadToDeg(temp_data.gHdt);
625 m_watchdogs.heading_watchdog = gps_watchdog_timeout_ticks;
629 if (!N2kIsNA(temp_data.gHdm)){
630 gHdm = GeodesicRadToDeg(temp_data.gHdm);
631 if (EvalPriority(n2k_msg, active_priority_heading, priority_map_heading)) {
633 if(!std::isnan(gHdt))
634 m_watchdogs.heading_watchdog = gps_watchdog_timeout_ticks;
642bool CommBridge::HandleN2K_129540(std::shared_ptr<const Nmea2000Msg> n2k_msg) {
644 std::vector<unsigned char> v = n2k_msg->payload;
647 ClearNavData(temp_data);
649 if (!m_decoder.DecodePGN129540(v, temp_data))
652 if (temp_data.n_satellites >= 0){
653 if (EvalPriority(n2k_msg, active_priority_satellites, priority_map_satellites)) {
654 g_SatsInView = temp_data.n_satellites;
656 m_watchdogs.satellite_watchdog = sat_watchdog_timeout_ticks;
663bool CommBridge::HandleN0183_RMC(std::shared_ptr<const Nmea0183Msg> n0183_msg) {
664 std::string str = n0183_msg->payload;
667 ClearNavData(temp_data);
669 if (!m_decoder.DecodeRMC(str, temp_data))
672 if (EvalPriority(n0183_msg, active_priority_position, priority_map_position)) {
673 gLat = temp_data.gLat;
674 gLon = temp_data.gLon;
675 m_watchdogs.position_watchdog = gps_watchdog_timeout_ticks;
678 if (EvalPriority(n0183_msg, active_priority_velocity, priority_map_velocity)) {
679 gSog = temp_data.gSog;
680 gCog = temp_data.gCog;
681 m_watchdogs.velocity_watchdog = gps_watchdog_timeout_ticks;
684 if (!std::isnan(temp_data.gVar)){
685 if (EvalPriority(n0183_msg, active_priority_variation, priority_map_variation)) {
686 gVar = temp_data.gVar;
687 m_watchdogs.variation_watchdog = gps_watchdog_timeout_ticks;
695bool CommBridge::HandleN0183_HDT(std::shared_ptr<const Nmea0183Msg> n0183_msg) {
696 std::string str = n0183_msg->payload;
698 ClearNavData(temp_data);
700 if (!m_decoder.DecodeHDT(str, temp_data))
703 if (EvalPriority(n0183_msg, active_priority_heading, priority_map_heading)) {
704 gHdt = temp_data.gHdt;
705 m_watchdogs.heading_watchdog = gps_watchdog_timeout_ticks;
713bool CommBridge::HandleN0183_HDG(std::shared_ptr<const Nmea0183Msg> n0183_msg) {
714 std::string str = n0183_msg->payload;
716 ClearNavData(temp_data);
718 if (!m_decoder.DecodeHDG(str, temp_data))
return false;
721 if (EvalPriority(n0183_msg, active_priority_heading, priority_map_heading)) {
722 gHdm = temp_data.gHdm;
723 m_watchdogs.heading_watchdog = gps_watchdog_timeout_ticks;
727 if (!std::isnan(temp_data.gVar)){
728 if (EvalPriority(n0183_msg, active_priority_variation, priority_map_variation)) {
729 gVar = temp_data.gVar;
730 m_watchdogs.variation_watchdog = gps_watchdog_timeout_ticks;
741bool CommBridge::HandleN0183_HDM(std::shared_ptr<const Nmea0183Msg> n0183_msg) {
742 std::string str = n0183_msg->payload;
744 ClearNavData(temp_data);
746 if (!m_decoder.DecodeHDM(str, temp_data))
return false;
748 if (EvalPriority(n0183_msg, active_priority_heading, priority_map_heading)) {
749 gHdm = temp_data.gHdm;
751 m_watchdogs.heading_watchdog = gps_watchdog_timeout_ticks;
758bool CommBridge::HandleN0183_VTG(std::shared_ptr<const Nmea0183Msg> n0183_msg) {
759 std::string str = n0183_msg->payload;
761 ClearNavData(temp_data);
763 if (!m_decoder.DecodeVTG(str, temp_data))
return false;
765 if (EvalPriority(n0183_msg, active_priority_velocity, priority_map_velocity)) {
766 gSog = temp_data.gSog;
767 gCog = temp_data.gCog;
768 m_watchdogs.velocity_watchdog = gps_watchdog_timeout_ticks;
775bool CommBridge::HandleN0183_GSV(std::shared_ptr<const Nmea0183Msg> n0183_msg) {
776 std::string str = n0183_msg->payload;
778 ClearNavData(temp_data);
780 if (!m_decoder.DecodeGSV(str, temp_data))
return false;
782 if (EvalPriority(n0183_msg, active_priority_satellites, priority_map_satellites)) {
783 if (temp_data.n_satellites >= 0){
784 g_SatsInView = temp_data.n_satellites;
787 m_watchdogs.satellite_watchdog = sat_watchdog_timeout_ticks;
795bool CommBridge::HandleN0183_GGA(std::shared_ptr<const Nmea0183Msg> n0183_msg) {
796 std::string str = n0183_msg->payload;
798 ClearNavData(temp_data);
800 if (!m_decoder.DecodeGGA(str, temp_data))
return false;
802 if (EvalPriority(n0183_msg, active_priority_position, priority_map_position)) {
803 gLat = temp_data.gLat;
804 gLon = temp_data.gLon;
805 m_watchdogs.position_watchdog = gps_watchdog_timeout_ticks;
808 if (EvalPriority(n0183_msg, active_priority_satellites, priority_map_satellites)) {
809 if (temp_data.n_satellites >= 0){
810 g_SatsInView = temp_data.n_satellites;
813 m_watchdogs.satellite_watchdog = sat_watchdog_timeout_ticks;
821bool CommBridge::HandleN0183_GLL(std::shared_ptr<const Nmea0183Msg> n0183_msg) {
822 std::string str = n0183_msg->payload;
824 ClearNavData(temp_data);
826 if (!m_decoder.DecodeGLL(str, temp_data))
return false;
828 if (EvalPriority(n0183_msg, active_priority_position, priority_map_position)) {
829 gLat = temp_data.gLat;
830 gLon = temp_data.gLon;
831 m_watchdogs.position_watchdog = gps_watchdog_timeout_ticks;
838bool CommBridge::HandleN0183_AIVDO(
839 std::shared_ptr<const Nmea0183Msg> n0183_msg) {
840 std::string str = n0183_msg->payload;
843 wxString sentence(str.c_str());
845 AisError nerr = AIS_GENERIC_ERROR;
846 nerr = DecodeSingleVDO(sentence, &gpd);
848 if (nerr == AIS_NoError) {
850 if (!std::isnan(gpd.kLat) && !std::isnan(gpd.kLon)){
851 if (EvalPriority(n0183_msg, active_priority_position, priority_map_position)) {
854 m_watchdogs.position_watchdog = gps_watchdog_timeout_ticks;
858 if (!std::isnan(gpd.kCog) && !std::isnan(gpd.kSog)){
859 if (EvalPriority(n0183_msg, active_priority_velocity, priority_map_velocity)) {
862 m_watchdogs.velocity_watchdog = gps_watchdog_timeout_ticks;
866 if (!std::isnan(gpd.kHdt)) {
867 if (EvalPriority(n0183_msg, active_priority_heading, priority_map_heading)) {
869 m_watchdogs.heading_watchdog = gps_watchdog_timeout_ticks;
878bool CommBridge::HandleSignalK(std::shared_ptr<const SignalkMsg> sK_msg){
879 std::string str = sK_msg->raw_message;
882 if (sK_msg->context_self != sK_msg->context)
885 g_ownshipMMSI_SK = sK_msg->context_self;
888 ClearNavData(temp_data);
890 if (!m_decoder.DecodeSignalK(str, temp_data))
return false;
893 if (!std::isnan(temp_data.gLat) && !std::isnan(temp_data.gLon)){
894 if (EvalPriority(sK_msg, active_priority_position, priority_map_position)) {
895 gLat = temp_data.gLat;
896 gLon = temp_data.gLon;
897 m_watchdogs.position_watchdog = gps_watchdog_timeout_ticks;
901 if (!std::isnan(temp_data.gSog)){
902 if (EvalPriority(sK_msg, active_priority_velocity, priority_map_velocity)) {
903 gSog = temp_data.gSog;
904 if((gSog > 0) && !std::isnan(temp_data.gCog))
905 gCog = temp_data.gCog;
906 m_watchdogs.velocity_watchdog = gps_watchdog_timeout_ticks;
910 if (!std::isnan(temp_data.gHdt)){
911 if (EvalPriority(sK_msg, active_priority_heading, priority_map_heading)) {
912 gHdt = temp_data.gHdt;
913 m_watchdogs.heading_watchdog = gps_watchdog_timeout_ticks;
917 if (!std::isnan(temp_data.gHdm)){
918 if (EvalPriority(sK_msg, active_priority_heading, priority_map_heading)) {
919 gHdm = temp_data.gHdm;
921 m_watchdogs.heading_watchdog = gps_watchdog_timeout_ticks;
925 if (!std::isnan(temp_data.gVar)){
926 if (EvalPriority(sK_msg, active_priority_variation, priority_map_variation)) {
927 gVar = temp_data.gVar;
928 m_watchdogs.variation_watchdog = gps_watchdog_timeout_ticks;
932 if (temp_data.n_satellites > 0){
933 if (EvalPriority(sK_msg, active_priority_satellites, priority_map_satellites)) {
934 g_SatsInView = temp_data.n_satellites;
937 m_watchdogs.satellite_watchdog = sat_watchdog_timeout_ticks;
946void CommBridge::InitializePriorityContainers(){
947 active_priority_position.active_priority = 0;
948 active_priority_velocity.active_priority = 0;
949 active_priority_heading.active_priority = 0;
950 active_priority_variation.active_priority = 0;
951 active_priority_satellites.active_priority = 0;
953 active_priority_position.active_source.clear();
954 active_priority_velocity.active_source.clear();
955 active_priority_heading.active_source.clear();
956 active_priority_variation.active_source.clear();
957 active_priority_satellites.active_source.clear();
959 active_priority_position.active_identifier.clear();
960 active_priority_velocity.active_identifier.clear();
961 active_priority_heading.active_identifier.clear();
962 active_priority_variation.active_identifier.clear();
963 active_priority_satellites.active_identifier.clear();
965 active_priority_position.pcclass =
"position";
966 active_priority_velocity.pcclass =
"velocity";
967 active_priority_heading.pcclass =
"heading";
968 active_priority_variation.pcclass =
"variation";
969 active_priority_satellites.pcclass =
"satellites";
971 active_priority_position.active_source_address = -1;
972 active_priority_velocity.active_source_address = -1;
973 active_priority_heading.active_source_address = -1;
974 active_priority_variation.active_source_address = -1;
975 active_priority_satellites.active_source_address = -1;
977 active_priority_void.active_priority = -1;
981void CommBridge::ClearPriorityMaps(){
982 priority_map_position.clear();
983 priority_map_velocity.clear();
984 priority_map_heading.clear();
985 priority_map_variation.clear();
986 priority_map_satellites.clear();
990 if (!category.compare(
"position"))
991 return active_priority_position;
992 else if (!category.compare(
"velocity"))
993 return active_priority_velocity;
994 else if (!category.compare(
"heading"))
995 return active_priority_heading;
996 else if (!category.compare(
"variation"))
997 return active_priority_variation;
998 else if (!category.compare(
"satellites"))
999 return active_priority_satellites;
1001 return active_priority_void;
1004void CommBridge::UpdateAndApplyMaps(std::vector<std::string> new_maps){
1005 ApplyPriorityMaps(new_maps);
1007 PresetPriorityContainers();
1011bool CommBridge::LoadConfig(
void )
1013 if( TheBaseConfig() ) {
1014 TheBaseConfig()->SetPath(
"/Settings/CommPriority");
1016 std::vector<std::string> new_maps;
1018 wxString pri_string;
1020 TheBaseConfig()->Read(
"PriorityPosition", &pri_string );
1021 s_prio = std::string(pri_string.c_str());
1022 new_maps.push_back(s_prio);
1024 TheBaseConfig()->Read(
"PriorityVelocity", &pri_string );
1025 s_prio = std::string(pri_string.c_str());
1026 new_maps.push_back(s_prio);
1028 TheBaseConfig()->Read(
"PriorityHeading", &pri_string );
1029 s_prio = std::string(pri_string.c_str());
1030 new_maps.push_back(s_prio);
1032 TheBaseConfig()->Read(
"PriorityVariation", &pri_string );
1033 s_prio = std::string(pri_string.c_str());
1034 new_maps.push_back(s_prio);
1036 TheBaseConfig()->Read(
"PrioritySatellites", &pri_string );
1037 s_prio = std::string(pri_string.c_str());
1038 new_maps.push_back(s_prio);
1040 ApplyPriorityMaps(new_maps);
1045bool CommBridge::SaveConfig(
void )
1047 if( TheBaseConfig() ) {
1048 TheBaseConfig()->SetPath(
"/Settings/CommPriority");
1050 wxString pri_string;
1051 pri_string = wxString(GetPriorityMap(priority_map_position).c_str());
1052 TheBaseConfig()->Write(
"PriorityPosition", pri_string );
1054 pri_string = wxString(GetPriorityMap(priority_map_velocity).c_str());
1055 TheBaseConfig()->Write(
"PriorityVelocity", pri_string );
1057 pri_string = wxString(GetPriorityMap(priority_map_heading).c_str());
1058 TheBaseConfig()->Write(
"PriorityHeading", pri_string );
1060 pri_string = wxString(GetPriorityMap(priority_map_variation).c_str());
1061 TheBaseConfig()->Write(
"PriorityVariation", pri_string );
1063 pri_string = wxString(GetPriorityMap(priority_map_satellites).c_str());
1064 TheBaseConfig()->Write(
"PrioritySatellites", pri_string );
1071std::string CommBridge::GetPriorityKey(std::shared_ptr <const NavMsg> msg){
1072 std::string source = msg->source->to_string();
1073 std::string listener_key = msg->key();
1076 std::string this_identifier;
1077 std::string this_address(
"0");
1078 if(msg->bus == NavAddr::Bus::N0183){
1079 auto msg_0183 = std::dynamic_pointer_cast<const Nmea0183Msg>(msg);
1081 this_identifier = msg_0183->talker;
1082 this_identifier += msg_0183->type;
1085 else if(msg->bus == NavAddr::Bus::N2000){
1086 auto msg_n2k = std::dynamic_pointer_cast<const Nmea2000Msg>(msg);
1088 this_identifier = msg_n2k->PGN.to_string();
1089 unsigned char n_source = msg_n2k->payload.at(7);
1091 sprintf(ss,
"%d",n_source);
1092 this_address = std::string(ss);
1095 else if(msg->bus == NavAddr::Bus::Signalk){
1096 auto msg_sk = std::dynamic_pointer_cast<const SignalkMsg>(msg);
1098 this_identifier =
"signalK";
1103 return source +
":" + this_address +
";" + this_identifier;
1107bool CommBridge::EvalPriority(std::shared_ptr <const NavMsg> msg,
1109 std::unordered_map<std::string, int>& priority_map) {
1111 std::string this_key = GetPriorityKey(msg);
1112 if (debug_priority) printf(
"This Key: %s\n", this_key.c_str());
1115 wxStringTokenizer tkz(this_key, _T(
";"));
1116 wxString wxs_this_source = tkz.GetNextToken();
1117 std::string source = wxs_this_source.ToStdString();
1118 wxString wxs_this_identifier = tkz.GetNextToken();
1119 std::string this_identifier = wxs_this_identifier.ToStdString();
1121 wxStringTokenizer tka(wxs_this_source, _T(
":"));
1123 int source_address = atoi(tka.GetNextToken().ToStdString().c_str());
1128 auto it = priority_map.find(this_key);
1129 if (it == priority_map.end()) {
1131 priority_map[this_key] = 0;
1134 this_priority = priority_map[this_key];
1136 for (
auto it = priority_map.begin(); it != priority_map.end(); it++) {
1137 if (debug_priority) printf(
" priority_map: %s %d\n", it->first.c_str(), it->second);
1142 if (this_priority > active_priority.active_priority){
1143 if (debug_priority) printf(
" Drop low priority: %s %d %d \n", source.c_str(), this_priority,
1144 active_priority.active_priority);
1149 if (this_priority < active_priority.active_priority){
1150 active_priority.active_priority = this_priority;
1151 active_priority.active_source = source;
1152 active_priority.active_identifier = this_identifier;
1153 active_priority.active_source_address = source_address;
1155 if (debug_priority) printf(
" Restoring high priority: %s %d\n", source.c_str(), this_priority);
1163 if (active_priority.active_source.size()){
1165 if (debug_priority) printf(
"source: %s\n", source.c_str());
1166 if (debug_priority) printf(
"active_source: %s\n", active_priority.active_source.c_str());
1168 if (source.compare(active_priority.active_source) != 0){
1172 int lowest_priority = -10;
1173 for (
auto it = priority_map.begin(); it != priority_map.end(); it++) {
1174 if (it->second > lowest_priority)
1175 lowest_priority = it->second;
1178 priority_map[this_key] = lowest_priority + 1;
1179 if (debug_priority) printf(
" Lowering priority A: %s :%d\n", source.c_str(), priority_map[this_key]);
1188 if(msg->bus == NavAddr::Bus::N0183){
1189 auto msg_0183 = std::dynamic_pointer_cast<const Nmea0183Msg>(msg);
1191 if (active_priority.active_identifier.size()){
1193 if (debug_priority) printf(
"this_identifier: %s\n", this_identifier.c_str());
1194 if (debug_priority) printf(
"active_priority.active_identifier: %s\n", active_priority.active_identifier.c_str());
1196 if (this_identifier.compare(active_priority.active_identifier) != 0){
1199 if (priority_map[this_key] == active_priority.active_priority){
1200 int lowest_priority = -10;
1201 for (
auto it = priority_map.begin(); it != priority_map.end(); it++) {
1202 if (it->second > lowest_priority)
1203 lowest_priority = it->second;
1206 priority_map[this_key] = lowest_priority + 1;
1207 if (debug_priority) printf(
" Lowering priority B: %s :%d\n", source.c_str(), priority_map[this_key]);
1218 else if(msg->bus == NavAddr::Bus::N2000){
1219 auto msg_n2k = std::dynamic_pointer_cast<const Nmea2000Msg>(msg);
1221 if (active_priority.active_identifier.size()){
1222 if (this_identifier.compare(active_priority.active_identifier) != 0){
1225 if (priority_map[this_key] == active_priority.active_priority){
1226 int lowest_priority = -10;
1227 for (
auto it = priority_map.begin(); it != priority_map.end(); it++) {
1228 if (it->second > lowest_priority)
1229 lowest_priority = it->second;
1232 priority_map[this_key] = lowest_priority + 1;
1233 if (debug_priority) printf(
" Lowering priority: %s :%d\n", source.c_str(), priority_map[this_key]);
1244 active_priority.active_source = source;
1245 active_priority.active_identifier = this_identifier;
1246 active_priority.active_source_address = source_address;
1247 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.
Handle most incoming messages and make them available for other parties.
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, raw SignalK message.
Data for selected source from multiple candidates.